1 /******************************************************************************
2 * $Id: rmfdataset.cpp 27384 2014-05-24 12:28:12Z rouault $
3 *
4 * Project: Raster Matrix Format
5 * Purpose: Read/write raster files used in GIS "Integratsia"
6 * (also known as "Panorama" GIS).
7 * Author: Andrey Kiselev, dron@ak4719.spb.edu
8 *
9 ******************************************************************************
10 * Copyright (c) 2005, Andrey Kiselev <dron@ak4719.spb.edu>
11 * Copyright (c) 2007-2012, Even Rouault <even dot rouault at mines-paris dot org>
12 *
13 * Permission is hereby granted, free of charge, to any person obtaining a
14 * copy of this software and associated documentation files (the "Software"),
15 * to deal in the Software without restriction, including without limitation
16 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 * and/or sell copies of the Software, and to permit persons to whom the
18 * Software is furnished to do so, subject to the following conditions:
19 *
20 * The above copyright notice and this permission notice shall be included
21 * in all copies or substantial portions of the Software.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 * DEALINGS IN THE SOFTWARE.
29 ****************************************************************************/
30
31 #include "ogr_spatialref.h"
32 #include "cpl_string.h"
33
34 #include "rmfdataset.h"
35
36 CPL_CVSID("$Id: rmfdataset.cpp 27384 2014-05-24 12:28:12Z rouault $");
37
38 CPL_C_START
39 void GDALRegister_RMF(void);
40 CPL_C_END
41
42 #define RMF_DEFAULT_BLOCKXSIZE 256
43 #define RMF_DEFAULT_BLOCKYSIZE 256
44
45 static const char RMF_SigRSW[] = { 'R', 'S', 'W', '\0' };
46 static const char RMF_SigRSW_BE[] = { '\0', 'W', 'S', 'R' };
47 static const char RMF_SigMTW[] = { 'M', 'T', 'W', '\0' };
48
49 static const char RMF_UnitsEmpty[] = "";
50 static const char RMF_UnitsM[] = "m";
51 static const char RMF_UnitsCM[] = "cm";
52 static const char RMF_UnitsDM[] = "dm";
53 static const char RMF_UnitsMM[] = "mm";
54
55 /************************************************************************/
56 /* ==================================================================== */
57 /* RMFRasterBand */
58 /* ==================================================================== */
59 /************************************************************************/
60
61 /************************************************************************/
62 /* RMFRasterBand() */
63 /************************************************************************/
64
RMFRasterBand(RMFDataset * poDS,int nBand,GDALDataType eType)65 RMFRasterBand::RMFRasterBand( RMFDataset *poDS, int nBand,
66 GDALDataType eType )
67 {
68 this->poDS = poDS;
69 this->nBand = nBand;
70
71 eDataType = eType;
72 nBytesPerPixel = poDS->sHeader.nBitDepth / 8;
73 nDataSize = GDALGetDataTypeSize( eDataType ) / 8;
74 nBlockXSize = poDS->sHeader.nTileWidth;
75 nBlockYSize = poDS->sHeader.nTileHeight;
76 nBlockSize = nBlockXSize * nBlockYSize;
77 nBlockBytes = nBlockSize * nDataSize;
78 nLastTileXBytes =
79 (poDS->GetRasterXSize() % poDS->sHeader.nTileWidth) * nDataSize;
80 nLastTileHeight = poDS->GetRasterYSize() % poDS->sHeader.nTileHeight;
81
82 #ifdef DEBUG
83 CPLDebug( "RMF",
84 "Band %d: tile width is %d, tile height is %d, "
85 " last tile width %d, last tile height %d, "
86 "bytes per pixel is %d, data type size is %d",
87 nBand, nBlockXSize, nBlockYSize,
88 poDS->sHeader.nLastTileWidth, poDS->sHeader.nLastTileHeight,
89 nBytesPerPixel, nDataSize );
90 #endif
91 }
92
93 /************************************************************************/
94 /* ~RMFRasterBand() */
95 /************************************************************************/
96
~RMFRasterBand()97 RMFRasterBand::~RMFRasterBand()
98 {
99 }
100
101 /************************************************************************/
102 /* ReadBuffer() */
103 /* */
104 /* Helper fucntion to read specified amount of bytes from the input */
105 /* file stream. */
106 /************************************************************************/
107
ReadBuffer(GByte * pabyBuf,GUInt32 nBytes) const108 CPLErr RMFRasterBand::ReadBuffer( GByte *pabyBuf, GUInt32 nBytes ) const
109 {
110 RMFDataset *poGDS = (RMFDataset *) poDS;
111
112 CPLAssert( pabyBuf != NULL && poGDS->fp != 0 );
113
114 vsi_l_offset nOffset = VSIFTellL( poGDS->fp );
115
116 if ( VSIFReadL( pabyBuf, 1, nBytes, poGDS->fp ) < nBytes )
117 {
118 // XXX
119 if( poGDS->eAccess == GA_Update )
120 {
121 return CE_Failure;
122 }
123 else
124 {
125 CPLError( CE_Failure, CPLE_FileIO,
126 "Can't read at offset %ld from input file.\n%s\n",
127 (long)nOffset, VSIStrerror( errno ) );
128 return CE_Failure;
129 }
130 }
131
132 #ifdef CPL_MSB
133 if ( poGDS->eRMFType == RMFT_MTW )
134 {
135 GUInt32 i;
136
137 if ( poGDS->sHeader.nBitDepth == 16 )
138 {
139 for ( i = 0; i < nBytes; i += 2 )
140 CPL_SWAP16PTR( pabyBuf + i );
141 }
142
143 else if ( poGDS->sHeader.nBitDepth == 32 )
144 {
145 for ( i = 0; i < nBytes; i += 4 )
146 CPL_SWAP32PTR( pabyBuf + i );
147 }
148
149 else if ( poGDS->sHeader.nBitDepth == 64 )
150 {
151 for ( i = 0; i < nBytes; i += 8 )
152 CPL_SWAPDOUBLE( pabyBuf + i );
153 }
154 }
155 #endif
156
157 return CE_None;
158 }
159
160 /************************************************************************/
161 /* IReadBlock() */
162 /************************************************************************/
163
IReadBlock(int nBlockXOff,int nBlockYOff,void * pImage)164 CPLErr RMFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
165 void * pImage )
166 {
167 RMFDataset *poGDS = (RMFDataset *) poDS;
168 GUInt32 nTile = nBlockYOff * poGDS->nXTiles + nBlockXOff;
169 GUInt32 nTileBytes;
170 GUInt32 nCurBlockYSize;
171
172 CPLAssert( poGDS != NULL
173 && nBlockXOff >= 0
174 && nBlockYOff >= 0
175 && pImage != NULL );
176
177 memset( pImage, 0, nBlockBytes );
178
179 if (2 * nTile + 1 >= poGDS->sHeader.nTileTblSize / sizeof(GUInt32))
180 {
181 return CE_Failure;
182 }
183
184 nTileBytes = poGDS->paiTiles[2 * nTile + 1];
185
186 if ( poGDS->sHeader.nLastTileHeight
187 && (GUInt32) nBlockYOff == poGDS->nYTiles - 1 )
188 nCurBlockYSize = poGDS->sHeader.nLastTileHeight;
189 else
190 nCurBlockYSize = nBlockYSize;
191
192 if ( VSIFSeekL( poGDS->fp, poGDS->paiTiles[2 * nTile], SEEK_SET ) < 0 )
193 {
194 // XXX: We will not report error here, because file just may be
195 // in update state and data for this block will be available later
196 if( poGDS->eAccess == GA_Update )
197 return CE_None;
198 else
199 {
200 CPLError( CE_Failure, CPLE_FileIO,
201 "Can't seek to offset %ld in input file to read data.\n%s\n",
202 (long) poGDS->paiTiles[2 * nTile], VSIStrerror( errno ) );
203 return CE_Failure;
204 }
205 }
206
207 if ( poGDS->nBands == 1 &&
208 ( poGDS->sHeader.nBitDepth == 8
209 || poGDS->sHeader.nBitDepth == 16
210 || poGDS->sHeader.nBitDepth == 32
211 || poGDS->sHeader.nBitDepth == 64 ) )
212 {
213 if ( nTileBytes > nBlockBytes )
214 nTileBytes = nBlockBytes;
215
216 /* -------------------------------------------------------------------- */
217 /* Decompress buffer, if needed. */
218 /* -------------------------------------------------------------------- */
219 if ( poGDS->Decompress )
220 {
221 GUInt32 nRawBytes;
222
223 if ( nLastTileXBytes && (GUInt32)nBlockXOff == poGDS->nXTiles - 1 )
224 nRawBytes = nLastTileXBytes;
225 else
226 nRawBytes = poGDS->nBands * nBlockXSize * nDataSize;
227
228 if ( nLastTileHeight && (GUInt32)nBlockYOff == poGDS->nYTiles - 1 )
229 nRawBytes *= nLastTileHeight;
230 else
231 nRawBytes *= nBlockYSize;
232
233 if ( nRawBytes > nTileBytes )
234 {
235 GByte *pabyTile = (GByte *) VSIMalloc( nTileBytes );
236
237 if ( !pabyTile )
238 {
239 CPLError( CE_Failure, CPLE_FileIO,
240 "Can't allocate tile block of size %lu.\n%s\n",
241 (unsigned long) nTileBytes, VSIStrerror( errno ) );
242 return CE_Failure;
243 }
244
245 if ( ReadBuffer( pabyTile, nTileBytes ) == CE_Failure )
246 {
247 // XXX: Do not fail here, just return empty block
248 // and continue reading.
249 CPLFree( pabyTile );
250 return CE_None;
251 }
252
253 (*poGDS->Decompress)( pabyTile, nTileBytes,
254 (GByte*)pImage, nRawBytes );
255 CPLFree( pabyTile );
256 nTileBytes = nRawBytes;
257 }
258 else
259 {
260 if ( ReadBuffer( (GByte *)pImage, nTileBytes ) == CE_Failure )
261 {
262 // XXX: Do not fail here, just return empty block
263 // and continue reading.
264 return CE_None;
265 }
266 }
267 }
268
269 else
270 {
271
272 if ( ReadBuffer( (GByte *)pImage, nTileBytes ) == CE_Failure )
273 {
274 // XXX: Do not fail here, just return empty block
275 // and continue reading.
276 return CE_None;
277 }
278
279 }
280
281 }
282
283 else if ( poGDS->eRMFType == RMFT_RSW )
284 {
285 GByte *pabyTile = (GByte *) VSIMalloc( nTileBytes );
286
287 if ( !pabyTile )
288 {
289 CPLError( CE_Failure, CPLE_FileIO,
290 "Can't allocate tile block of size %lu.\n%s\n",
291 (unsigned long) nTileBytes, VSIStrerror( errno ) );
292 return CE_Failure;
293 }
294
295
296 if ( ReadBuffer( pabyTile, nTileBytes ) == CE_Failure )
297 {
298 // XXX: Do not fail here, just return empty block
299 // and continue reading.
300 CPLFree( pabyTile );
301 return CE_None;
302 }
303
304 /* -------------------------------------------------------------------- */
305 /* If buffer was compressed, decompress it first. */
306 /* -------------------------------------------------------------------- */
307 if ( poGDS->Decompress )
308 {
309 GUInt32 nRawBytes;
310
311 if ( nLastTileXBytes && (GUInt32)nBlockXOff == poGDS->nXTiles - 1 )
312 nRawBytes = nLastTileXBytes;
313 else
314 nRawBytes = poGDS->nBands * nBlockXSize * nDataSize;
315
316 if ( nLastTileHeight && (GUInt32)nBlockYOff == poGDS->nYTiles - 1 )
317 nRawBytes *= nLastTileHeight;
318 else
319 nRawBytes *= nBlockYSize;
320
321 if ( nRawBytes > nTileBytes )
322 {
323 GByte *pszRawBuf = (GByte *)VSIMalloc( nRawBytes );
324 if (pszRawBuf == NULL)
325 {
326 CPLError( CE_Failure, CPLE_FileIO,
327 "Can't allocate a buffer for raw data of size %lu.\n%s\n",
328 (unsigned long) nRawBytes, VSIStrerror( errno ) );
329
330 VSIFree( pabyTile );
331 return CE_Failure;
332 }
333
334 (*poGDS->Decompress)( pabyTile, nTileBytes,
335 pszRawBuf, nRawBytes );
336 CPLFree( pabyTile );
337 pabyTile = pszRawBuf;
338 nTileBytes = nRawBytes;
339 }
340 }
341
342 /* -------------------------------------------------------------------- */
343 /* Deinterleave pixels from input buffer. */
344 /* -------------------------------------------------------------------- */
345 GUInt32 i;
346
347 if ( poGDS->sHeader.nBitDepth == 24 || poGDS->sHeader.nBitDepth == 32 )
348 {
349 GUInt32 nTileSize = nTileBytes / nBytesPerPixel;
350
351 if ( nTileSize > nBlockSize )
352 nTileSize = nBlockSize;
353
354 for ( i = 0; i < nTileSize; i++ )
355 {
356 // Colour triplets in RMF file organized in reverse order:
357 // blue, green, red. When we have 32-bit RMF the forth byte
358 // in quadriplet should be discarded as it has no meaning.
359 // That is why we always use 3 byte count in the following
360 // pabyTemp index.
361 ((GByte *) pImage)[i] =
362 pabyTile[i * nBytesPerPixel + 3 - nBand];
363 }
364 }
365
366 else if ( poGDS->sHeader.nBitDepth == 16 )
367 {
368 GUInt32 nTileSize = nTileBytes / nBytesPerPixel;
369
370 if ( nTileSize > nBlockSize )
371 nTileSize = nBlockSize;
372
373 for ( i = 0; i < nTileSize; i++ )
374 {
375 switch ( nBand )
376 {
377 case 1:
378 ((GByte *) pImage)[i] =
379 (GByte)((((GUInt16*)pabyTile)[i] & 0x7c00) >> 7);
380 break;
381 case 2:
382 ((GByte *) pImage)[i] =
383 (GByte)((((GUInt16*)pabyTile)[i] & 0x03e0) >> 2);
384 break;
385 case 3:
386 ((GByte *) pImage)[i] =
387 (GByte)(((GUInt16*)pabyTile)[i] & 0x1F) << 3;
388 break;
389 default:
390 break;
391 }
392 }
393 }
394
395 else if ( poGDS->sHeader.nBitDepth == 4 )
396 {
397 GByte *pabyTemp = pabyTile;
398
399 for ( i = 0; i < nBlockSize; i++ )
400 {
401 // Most significant part of the byte represents leftmost pixel
402 if ( i & 0x01 )
403 ((GByte *) pImage)[i] = *pabyTemp++ & 0x0F;
404 else
405 ((GByte *) pImage)[i] = (*pabyTemp & 0xF0) >> 4;
406 }
407 }
408
409 else if ( poGDS->sHeader.nBitDepth == 1 )
410 {
411 GByte *pabyTemp = pabyTile;
412
413 for ( i = 0; i < nBlockSize; i++ )
414 {
415 switch ( i & 0x7 )
416 {
417 case 0:
418 ((GByte *) pImage)[i] = (*pabyTemp & 0x80) >> 7;
419 break;
420 case 1:
421 ((GByte *) pImage)[i] = (*pabyTemp & 0x40) >> 6;
422 break;
423 case 2:
424 ((GByte *) pImage)[i] = (*pabyTemp & 0x20) >> 5;
425 break;
426 case 3:
427 ((GByte *) pImage)[i] = (*pabyTemp & 0x10) >> 4;
428 break;
429 case 4:
430 ((GByte *) pImage)[i] = (*pabyTemp & 0x08) >> 3;
431 break;
432 case 5:
433 ((GByte *) pImage)[i] = (*pabyTemp & 0x04) >> 2;
434 break;
435 case 6:
436 ((GByte *) pImage)[i] = (*pabyTemp & 0x02) >> 1;
437 break;
438 case 7:
439 ((GByte *) pImage)[i] = *pabyTemp++ & 0x01;
440 break;
441 default:
442 break;
443 }
444 }
445 }
446
447 CPLFree( pabyTile );
448 }
449
450 if ( nLastTileXBytes
451 && (GUInt32) nBlockXOff == poGDS->nXTiles - 1 )
452 {
453 GUInt32 iRow;
454
455 for ( iRow = nCurBlockYSize - 1; iRow > 0; iRow-- )
456 {
457 memmove( (GByte *)pImage + nBlockXSize * iRow * nDataSize,
458 (GByte *)pImage + iRow * nLastTileXBytes,
459 nLastTileXBytes );
460 }
461
462 }
463
464 return CE_None;
465 }
466
467 /************************************************************************/
468 /* IWriteBlock() */
469 /************************************************************************/
470
IWriteBlock(int nBlockXOff,int nBlockYOff,void * pImage)471 CPLErr RMFRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
472 void * pImage )
473 {
474 RMFDataset *poGDS = (RMFDataset *)poDS;
475 GUInt32 nTile = nBlockYOff * poGDS->nXTiles + nBlockXOff;
476 GUInt32 nTileBytes = nDataSize * poGDS->nBands;
477 GUInt32 iInPixel, iOutPixel, nCurBlockYSize;
478 GByte *pabyTile;
479
480 CPLAssert( poGDS != NULL
481 && nBlockXOff >= 0
482 && nBlockYOff >= 0
483 && pImage != NULL );
484
485 if ( poGDS->paiTiles[2 * nTile] )
486 {
487 if ( VSIFSeekL( poGDS->fp, poGDS->paiTiles[2 * nTile], SEEK_SET ) < 0 )
488 {
489 CPLError( CE_Failure, CPLE_FileIO,
490 "Can't seek to offset %ld in output file to write data.\n%s",
491 (long) poGDS->paiTiles[2 * nTile],
492 VSIStrerror( errno ) );
493 return CE_Failure;
494 }
495 }
496 else
497 {
498 if ( VSIFSeekL( poGDS->fp, 0, SEEK_END ) < 0 )
499 {
500 CPLError( CE_Failure, CPLE_FileIO,
501 "Can't seek to offset %ld in output file to write data.\n%s",
502 (long) poGDS->paiTiles[2 * nTile],
503 VSIStrerror( errno ) );
504 return CE_Failure;
505 }
506 poGDS->paiTiles[2 * nTile] = (GUInt32) VSIFTellL( poGDS->fp );
507
508 poGDS->bHeaderDirty = TRUE;
509 }
510
511 if ( nLastTileXBytes
512 && (GUInt32) nBlockXOff == poGDS->nXTiles - 1 )
513 nTileBytes *= poGDS->sHeader.nLastTileWidth;
514 else
515 nTileBytes *= nBlockXSize;
516
517 if ( poGDS->sHeader.nLastTileHeight
518 && (GUInt32) nBlockYOff == poGDS->nYTiles - 1 )
519 nCurBlockYSize = poGDS->sHeader.nLastTileHeight;
520 else
521 nCurBlockYSize = nBlockYSize;
522
523 nTileBytes *= nCurBlockYSize;
524
525 pabyTile = (GByte *) VSICalloc( nTileBytes, 1 );
526 if ( !pabyTile )
527 {
528 CPLError( CE_Failure, CPLE_FileIO,
529 "Can't allocate space for the tile blocak of size %lu.\n%s",
530 (unsigned long) nTileBytes, VSIStrerror( errno ) );
531 return CE_Failure;
532 }
533
534 if ( nLastTileXBytes
535 && (GUInt32) nBlockXOff == poGDS->nXTiles - 1 )
536 {
537 GUInt32 iRow;
538
539 if ( poGDS->nBands == 1 )
540 {
541 for ( iRow = 0; iRow < nCurBlockYSize; iRow++ )
542 {
543 memcpy( pabyTile + iRow * nLastTileXBytes,
544 (GByte*)pImage + nBlockXSize * iRow * nDataSize,
545 nLastTileXBytes );
546 }
547 }
548 else
549 {
550 if ( poGDS->paiTiles[2 * nTile + 1] )
551 {
552 VSIFReadL( pabyTile, 1, nTileBytes, poGDS->fp );
553 VSIFSeekL( poGDS->fp, poGDS->paiTiles[2 * nTile], SEEK_SET );
554 }
555
556 for ( iRow = 0; iRow < nCurBlockYSize; iRow++ )
557 {
558 for ( iInPixel = 0, iOutPixel = nBytesPerPixel - nBand;
559 iOutPixel < nLastTileXBytes * poGDS->nBands;
560 iInPixel++, iOutPixel += poGDS->nBands )
561 (pabyTile + iRow * nLastTileXBytes * poGDS->nBands)[iOutPixel] =
562 ((GByte *) pImage + nBlockXSize * iRow * nDataSize)[iInPixel];
563 }
564 }
565 }
566 else
567 {
568 if ( poGDS->nBands == 1 )
569 memcpy( pabyTile, pImage, nTileBytes );
570 else
571 {
572 if ( poGDS->paiTiles[2 * nTile + 1] )
573 {
574 VSIFReadL( pabyTile, 1, nTileBytes, poGDS->fp );
575 VSIFSeekL( poGDS->fp, poGDS->paiTiles[2 * nTile], SEEK_SET );
576 }
577
578 for ( iInPixel = 0, iOutPixel = nBytesPerPixel - nBand;
579 iOutPixel < nTileBytes;
580 iInPixel++, iOutPixel += poGDS->nBands )
581 pabyTile[iOutPixel] = ((GByte *) pImage)[iInPixel];
582
583 }
584 }
585
586 #ifdef CPL_MSB
587 if ( poGDS->eRMFType == RMFT_MTW )
588 {
589 GUInt32 i;
590
591 if ( poGDS->sHeader.nBitDepth == 16 )
592 {
593 for ( i = 0; i < nTileBytes; i += 2 )
594 CPL_SWAP16PTR( pabyTile + i );
595 }
596
597 else if ( poGDS->sHeader.nBitDepth == 32 )
598 {
599 for ( i = 0; i < nTileBytes; i += 4 )
600 CPL_SWAP32PTR( pabyTile + i );
601 }
602
603 else if ( poGDS->sHeader.nBitDepth == 64 )
604 {
605 for ( i = 0; i < nTileBytes; i += 8 )
606 CPL_SWAPDOUBLE( pabyTile + i );
607 }
608 }
609 #endif
610
611 if ( VSIFWriteL( pabyTile, 1, nTileBytes, poGDS->fp ) < nTileBytes )
612 {
613 CPLError( CE_Failure, CPLE_FileIO,
614 "Can't write block with X offset %d and Y offset %d.\n%s",
615 nBlockXOff, nBlockYOff, VSIStrerror( errno ) );
616 VSIFree( pabyTile );
617 return CE_Failure;
618 }
619
620 poGDS->paiTiles[2 * nTile + 1] = nTileBytes;
621 VSIFree( pabyTile );
622
623 poGDS->bHeaderDirty = TRUE;
624
625 return CE_None;
626 }
627
628 /************************************************************************/
629 /* GetUnitType() */
630 /************************************************************************/
631
GetUnitType()632 const char *RMFRasterBand::GetUnitType()
633
634 {
635 RMFDataset *poGDS = (RMFDataset *) poDS;
636
637 return (const char *)poGDS->pszUnitType;
638 }
639
640 /************************************************************************/
641 /* SetUnitType() */
642 /************************************************************************/
643
SetUnitType(const char * pszNewValue)644 CPLErr RMFRasterBand::SetUnitType( const char *pszNewValue )
645
646 {
647 RMFDataset *poGDS = (RMFDataset *) poDS;
648
649 CPLFree(poGDS->pszUnitType);
650 poGDS->pszUnitType = CPLStrdup( pszNewValue );
651
652 return CE_None;
653 }
654
655 /************************************************************************/
656 /* GetColorTable() */
657 /************************************************************************/
658
GetColorTable()659 GDALColorTable *RMFRasterBand::GetColorTable()
660 {
661 RMFDataset *poGDS = (RMFDataset *) poDS;
662
663 return poGDS->poColorTable;
664 }
665
666 /************************************************************************/
667 /* SetColorTable() */
668 /************************************************************************/
669
SetColorTable(GDALColorTable * poColorTable)670 CPLErr RMFRasterBand::SetColorTable( GDALColorTable *poColorTable )
671 {
672 RMFDataset *poGDS = (RMFDataset *) poDS;
673
674 if ( poColorTable )
675 {
676 if ( poGDS->eRMFType == RMFT_RSW && poGDS->nBands == 1 )
677 {
678 GDALColorEntry oEntry;
679 GUInt32 i;
680
681 if ( !poGDS->pabyColorTable )
682 return CE_Failure;
683
684 for( i = 0; i < poGDS->nColorTableSize; i++ )
685 {
686 poColorTable->GetColorEntryAsRGB( i, &oEntry );
687 poGDS->pabyColorTable[i * 4] = (GByte) oEntry.c1; // Red
688 poGDS->pabyColorTable[i * 4 + 1] = (GByte) oEntry.c2; // Green
689 poGDS->pabyColorTable[i * 4 + 2] = (GByte) oEntry.c3; // Blue
690 poGDS->pabyColorTable[i * 4 + 3] = 0;
691 }
692
693 poGDS->bHeaderDirty = TRUE;
694 }
695 }
696 else
697 return CE_Failure;
698
699 return CE_None;
700 }
701
702 /************************************************************************/
703 /* GetColorInterpretation() */
704 /************************************************************************/
705
GetColorInterpretation()706 GDALColorInterp RMFRasterBand::GetColorInterpretation()
707 {
708 RMFDataset *poGDS = (RMFDataset *) poDS;
709
710 if( poGDS->nBands == 3 )
711 {
712 if( nBand == 1 )
713 return GCI_RedBand;
714 else if( nBand == 2 )
715 return GCI_GreenBand;
716 else if( nBand == 3 )
717 return GCI_BlueBand;
718 else
719 return GCI_Undefined;
720 }
721 else
722 {
723 if ( poGDS->eRMFType == RMFT_RSW )
724 return GCI_PaletteIndex;
725 else
726 return GCI_Undefined;
727 }
728 }
729
730 /************************************************************************/
731 /* ==================================================================== */
732 /* RMFDataset */
733 /* ==================================================================== */
734 /************************************************************************/
735
736 /************************************************************************/
737 /* RMFDataset() */
738 /************************************************************************/
739
RMFDataset()740 RMFDataset::RMFDataset()
741 {
742 pszFilename = NULL;
743 fp = NULL;
744 nBands = 0;
745 nXTiles = 0;
746 nYTiles = 0;
747 paiTiles = NULL;
748 pszProjection = CPLStrdup( "" );
749 pszUnitType = CPLStrdup( RMF_UnitsEmpty );
750 adfGeoTransform[0] = 0.0;
751 adfGeoTransform[1] = 1.0;
752 adfGeoTransform[2] = 0.0;
753 adfGeoTransform[3] = 0.0;
754 adfGeoTransform[4] = 0.0;
755 adfGeoTransform[5] = 1.0;
756 pabyColorTable = NULL;
757 poColorTable = NULL;
758 eRMFType = RMFT_RSW;
759 memset( &sHeader, 0, sizeof(sHeader) );
760 memset( &sExtHeader, 0, sizeof(sExtHeader) );
761
762 Decompress = NULL;
763
764 bBigEndian = FALSE;
765 bHeaderDirty = FALSE;
766 }
767
768 /************************************************************************/
769 /* ~RMFDataset() */
770 /************************************************************************/
771
~RMFDataset()772 RMFDataset::~RMFDataset()
773 {
774 FlushCache();
775
776 if ( paiTiles )
777 CPLFree( paiTiles );
778 if ( pszProjection )
779 CPLFree( pszProjection );
780 if ( pszUnitType )
781 CPLFree( pszUnitType );
782 if ( pabyColorTable )
783 CPLFree( pabyColorTable );
784 if ( poColorTable != NULL )
785 delete poColorTable;
786 if( fp != NULL )
787 VSIFCloseL( fp );
788 }
789
790 /************************************************************************/
791 /* GetGeoTransform() */
792 /************************************************************************/
793
GetGeoTransform(double * padfTransform)794 CPLErr RMFDataset::GetGeoTransform( double * padfTransform )
795 {
796 memcpy( padfTransform, adfGeoTransform, sizeof(adfGeoTransform[0]) * 6 );
797
798 if( sHeader.iGeorefFlag )
799 return CE_None;
800 else
801 return CE_Failure;
802 }
803
804 /************************************************************************/
805 /* SetGeoTransform() */
806 /************************************************************************/
807
SetGeoTransform(double * padfTransform)808 CPLErr RMFDataset::SetGeoTransform( double * padfTransform )
809 {
810 memcpy( adfGeoTransform, padfTransform, sizeof(double) * 6 );
811 sHeader.dfPixelSize = adfGeoTransform[1];
812 if ( sHeader.dfPixelSize != 0.0 )
813 sHeader.dfResolution = sHeader.dfScale / sHeader.dfPixelSize;
814 sHeader.dfLLX = adfGeoTransform[0];
815 sHeader.dfLLY = adfGeoTransform[3] - nRasterYSize * sHeader.dfPixelSize;
816 sHeader.iGeorefFlag = 1;
817
818 bHeaderDirty = TRUE;
819
820 return CE_None;
821 }
822
823 /************************************************************************/
824 /* GetProjectionRef() */
825 /************************************************************************/
826
GetProjectionRef()827 const char *RMFDataset::GetProjectionRef()
828 {
829 if( pszProjection )
830 return pszProjection;
831 else
832 return "";
833 }
834
835 /************************************************************************/
836 /* SetProjection() */
837 /************************************************************************/
838
SetProjection(const char * pszNewProjection)839 CPLErr RMFDataset::SetProjection( const char * pszNewProjection )
840
841 {
842 if ( pszProjection )
843 CPLFree( pszProjection );
844 pszProjection = CPLStrdup( (pszNewProjection) ? pszNewProjection : "" );
845
846 bHeaderDirty = TRUE;
847
848 return CE_None;
849 }
850
851 /************************************************************************/
852 /* WriteHeader() */
853 /************************************************************************/
854
WriteHeader()855 CPLErr RMFDataset::WriteHeader()
856 {
857 /* -------------------------------------------------------------------- */
858 /* Setup projection. */
859 /* -------------------------------------------------------------------- */
860 if( pszProjection && !EQUAL( pszProjection, "" ) )
861 {
862 OGRSpatialReference oSRS;
863 long iProjection, iDatum, iEllips, iZone;
864 char *pszProj = pszProjection;
865
866 if ( oSRS.importFromWkt( &pszProj ) == OGRERR_NONE )
867 {
868 double adfPrjParams[7];
869
870 oSRS.exportToPanorama( &iProjection, &iDatum, &iEllips, &iZone,
871 adfPrjParams );
872 sHeader.iProjection = iProjection;
873 sHeader.dfStdP1 = adfPrjParams[0];
874 sHeader.dfStdP2 = adfPrjParams[1];
875 sHeader.dfCenterLat = adfPrjParams[2];
876 sHeader.dfCenterLong = adfPrjParams[3];
877
878 sExtHeader.nEllipsoid = iEllips;
879 sExtHeader.nDatum = iDatum;
880 sExtHeader.nZone = iZone;
881 }
882 }
883
884 #define RMF_WRITE_LONG( ptr, value, offset ) \
885 do { \
886 GInt32 iLong = CPL_LSBWORD32( value ); \
887 memcpy( (ptr) + (offset), &iLong, 4 ); \
888 } while(0);
889
890 #define RMF_WRITE_ULONG( ptr,value, offset ) \
891 do { \
892 GUInt32 iULong = CPL_LSBWORD32( value ); \
893 memcpy( (ptr) + (offset), &iULong, 4 ); \
894 } while(0);
895
896 #define RMF_WRITE_DOUBLE( ptr,value, offset ) \
897 do { \
898 double dfDouble = (value); \
899 CPL_LSBPTR64( &dfDouble ); \
900 memcpy( (ptr) + (offset), &dfDouble, 8 ); \
901 } while(0);
902
903 /* -------------------------------------------------------------------- */
904 /* Write out the main header. */
905 /* -------------------------------------------------------------------- */
906 {
907 GByte abyHeader[RMF_HEADER_SIZE];
908
909 memset( abyHeader, 0, sizeof(abyHeader) );
910
911 memcpy( abyHeader, sHeader.bySignature, RMF_SIGNATURE_SIZE );
912 RMF_WRITE_ULONG( abyHeader, sHeader.iVersion, 4 );
913 //
914 RMF_WRITE_ULONG( abyHeader, sHeader.nOvrOffset, 12 );
915 RMF_WRITE_ULONG( abyHeader, sHeader.iUserID, 16 );
916 memcpy( abyHeader + 20, sHeader.byName, RMF_NAME_SIZE );
917 RMF_WRITE_ULONG( abyHeader, sHeader.nBitDepth, 52 );
918 RMF_WRITE_ULONG( abyHeader, sHeader.nHeight, 56 );
919 RMF_WRITE_ULONG( abyHeader, sHeader.nWidth, 60 );
920 RMF_WRITE_ULONG( abyHeader, sHeader.nXTiles, 64 );
921 RMF_WRITE_ULONG( abyHeader, sHeader.nYTiles, 68 );
922 RMF_WRITE_ULONG( abyHeader, sHeader.nTileHeight, 72 );
923 RMF_WRITE_ULONG( abyHeader, sHeader.nTileWidth, 76 );
924 RMF_WRITE_ULONG( abyHeader, sHeader.nLastTileHeight, 80 );
925 RMF_WRITE_ULONG( abyHeader, sHeader.nLastTileWidth, 84 );
926 RMF_WRITE_ULONG( abyHeader, sHeader.nROIOffset, 88 );
927 RMF_WRITE_ULONG( abyHeader, sHeader.nROISize, 92 );
928 RMF_WRITE_ULONG( abyHeader, sHeader.nClrTblOffset, 96 );
929 RMF_WRITE_ULONG( abyHeader, sHeader.nClrTblSize, 100 );
930 RMF_WRITE_ULONG( abyHeader, sHeader.nTileTblOffset, 104 );
931 RMF_WRITE_ULONG( abyHeader, sHeader.nTileTblSize, 108 );
932 RMF_WRITE_LONG( abyHeader, sHeader.iMapType, 124 );
933 RMF_WRITE_LONG( abyHeader, sHeader.iProjection, 128 );
934 RMF_WRITE_DOUBLE( abyHeader, sHeader.dfScale, 136 );
935 RMF_WRITE_DOUBLE( abyHeader, sHeader.dfResolution, 144 );
936 RMF_WRITE_DOUBLE( abyHeader, sHeader.dfPixelSize, 152 );
937 RMF_WRITE_DOUBLE( abyHeader, sHeader.dfLLY, 160 );
938 RMF_WRITE_DOUBLE( abyHeader, sHeader.dfLLX, 168 );
939 RMF_WRITE_DOUBLE( abyHeader, sHeader.dfStdP1, 176 );
940 RMF_WRITE_DOUBLE( abyHeader, sHeader.dfStdP2, 184 );
941 RMF_WRITE_DOUBLE( abyHeader, sHeader.dfCenterLong, 192 );
942 RMF_WRITE_DOUBLE( abyHeader, sHeader.dfCenterLat, 200 );
943 *(abyHeader + 208) = sHeader.iCompression;
944 *(abyHeader + 209) = sHeader.iMaskType;
945 *(abyHeader + 210) = sHeader.iMaskStep;
946 *(abyHeader + 211) = sHeader.iFrameFlag;
947 RMF_WRITE_ULONG( abyHeader, sHeader.nFlagsTblOffset, 212 );
948 RMF_WRITE_ULONG( abyHeader, sHeader.nFlagsTblSize, 216 );
949 RMF_WRITE_ULONG( abyHeader, sHeader.nFileSize0, 220 );
950 RMF_WRITE_ULONG( abyHeader, sHeader.nFileSize1, 224 );
951 *(abyHeader + 228) = sHeader.iUnknown;
952 *(abyHeader + 244) = sHeader.iGeorefFlag;
953 *(abyHeader + 245) = sHeader.iInverse;
954 memcpy( abyHeader + 248, sHeader.abyInvisibleColors,
955 sizeof(sHeader.abyInvisibleColors) );
956 RMF_WRITE_DOUBLE( abyHeader, sHeader.adfElevMinMax[0], 280 );
957 RMF_WRITE_DOUBLE( abyHeader, sHeader.adfElevMinMax[1], 288 );
958 RMF_WRITE_DOUBLE( abyHeader, sHeader.dfNoData, 296 );
959 RMF_WRITE_ULONG( abyHeader, sHeader.iElevationUnit, 304 );
960 *(abyHeader + 308) = sHeader.iElevationType;
961 RMF_WRITE_ULONG( abyHeader, sHeader.nExtHdrOffset, 312 );
962 RMF_WRITE_ULONG( abyHeader, sHeader.nExtHdrSize, 316 );
963
964 VSIFSeekL( fp, 0, SEEK_SET );
965 VSIFWriteL( abyHeader, 1, sizeof(abyHeader), fp );
966 }
967
968 /* -------------------------------------------------------------------- */
969 /* Write out the extended header. */
970 /* -------------------------------------------------------------------- */
971
972 if ( sHeader.nExtHdrOffset && sHeader.nExtHdrSize )
973 {
974 GByte *pabyExtHeader = (GByte *)CPLCalloc( sHeader.nExtHdrSize, 1 );
975
976 RMF_WRITE_LONG( pabyExtHeader, sExtHeader.nEllipsoid, 24 );
977 RMF_WRITE_LONG( pabyExtHeader, sExtHeader.nDatum, 32 );
978 RMF_WRITE_LONG( pabyExtHeader, sExtHeader.nZone, 36 );
979
980 VSIFSeekL( fp, sHeader.nExtHdrOffset, SEEK_SET );
981 VSIFWriteL( pabyExtHeader, 1, sHeader.nExtHdrSize, fp );
982
983 CPLFree( pabyExtHeader );
984 }
985
986 #undef RMF_WRITE_DOUBLE
987 #undef RMF_WRITE_ULONG
988 #undef RMF_WRITE_LONG
989
990 /* -------------------------------------------------------------------- */
991 /* Write out the color table. */
992 /* -------------------------------------------------------------------- */
993
994 if ( sHeader.nClrTblOffset && sHeader.nClrTblSize )
995 {
996 VSIFSeekL( fp, sHeader.nClrTblOffset, SEEK_SET );
997 VSIFWriteL( pabyColorTable, 1, sHeader.nClrTblSize, fp );
998 }
999
1000 /* -------------------------------------------------------------------- */
1001 /* Write out the block table, swap if needed. */
1002 /* -------------------------------------------------------------------- */
1003
1004 VSIFSeekL( fp, sHeader.nTileTblOffset, SEEK_SET );
1005
1006 #ifdef CPL_MSB
1007 GUInt32 i;
1008 GUInt32 *paiTilesSwapped = (GUInt32 *)CPLMalloc( sHeader.nTileTblSize );
1009
1010 if ( !paiTilesSwapped )
1011 return CE_Failure;
1012
1013 memcpy( paiTilesSwapped, paiTiles, sHeader.nTileTblSize );
1014 for ( i = 0; i < sHeader.nTileTblSize / sizeof(GUInt32); i++ )
1015 CPL_SWAP32PTR( paiTilesSwapped + i );
1016 VSIFWriteL( paiTilesSwapped, 1, sHeader.nTileTblSize, fp );
1017
1018 CPLFree( paiTilesSwapped );
1019 #else
1020 VSIFWriteL( paiTiles, 1, sHeader.nTileTblSize, fp );
1021 #endif
1022
1023 bHeaderDirty = FALSE;
1024
1025 return CE_None;
1026 }
1027
1028 /************************************************************************/
1029 /* FlushCache() */
1030 /************************************************************************/
1031
FlushCache()1032 void RMFDataset::FlushCache()
1033
1034 {
1035 GDALDataset::FlushCache();
1036
1037 if ( !bHeaderDirty )
1038 return;
1039
1040 if ( eRMFType == RMFT_MTW )
1041 {
1042 GDALRasterBand *poBand = GetRasterBand(1);
1043
1044 if ( poBand )
1045 {
1046 poBand->ComputeRasterMinMax( FALSE, sHeader.adfElevMinMax );
1047 bHeaderDirty = TRUE;
1048 }
1049 }
1050 WriteHeader();
1051 }
1052
1053 /************************************************************************/
1054 /* Identify() */
1055 /************************************************************************/
1056
Identify(GDALOpenInfo * poOpenInfo)1057 int RMFDataset::Identify( GDALOpenInfo *poOpenInfo )
1058
1059 {
1060 if( poOpenInfo->pabyHeader == NULL)
1061 return FALSE;
1062
1063 if( memcmp(poOpenInfo->pabyHeader, RMF_SigRSW, sizeof(RMF_SigRSW)) != 0
1064 && memcmp(poOpenInfo->pabyHeader, RMF_SigRSW_BE, sizeof(RMF_SigRSW_BE)) != 0
1065 && memcmp(poOpenInfo->pabyHeader, RMF_SigMTW, sizeof(RMF_SigMTW)) != 0 )
1066 return FALSE;
1067
1068 return TRUE;
1069 }
1070
1071 /************************************************************************/
1072 /* Open() */
1073 /************************************************************************/
1074
Open(GDALOpenInfo * poOpenInfo)1075 GDALDataset *RMFDataset::Open( GDALOpenInfo * poOpenInfo )
1076 {
1077 if ( !Identify(poOpenInfo) )
1078 return NULL;
1079
1080 /* -------------------------------------------------------------------- */
1081 /* Create a corresponding GDALDataset. */
1082 /* -------------------------------------------------------------------- */
1083 RMFDataset *poDS;
1084
1085 poDS = new RMFDataset();
1086
1087 if( poOpenInfo->eAccess == GA_ReadOnly )
1088 poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
1089 else
1090 poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "r+b" );
1091 if ( !poDS->fp )
1092 {
1093 delete poDS;
1094 return NULL;
1095 }
1096
1097 #define RMF_READ_ULONG(ptr, value, offset) \
1098 do { \
1099 if ( poDS->bBigEndian ) \
1100 { \
1101 (value) = CPL_MSBWORD32(*(GUInt32*)((ptr) + (offset))); \
1102 } \
1103 else \
1104 { \
1105 (value) = CPL_LSBWORD32(*(GUInt32*)((ptr) + (offset))); \
1106 } \
1107 } while(0);
1108
1109 #define RMF_READ_LONG(ptr, value, offset) \
1110 do { \
1111 if ( poDS->bBigEndian ) \
1112 { \
1113 (value) = CPL_MSBWORD32(*(GInt32*)((ptr) + (offset))); \
1114 } \
1115 else \
1116 { \
1117 (value) = CPL_LSBWORD32(*(GInt32*)((ptr) + (offset))); \
1118 } \
1119 } while(0);
1120
1121 #define RMF_READ_DOUBLE(ptr, value, offset) \
1122 do { \
1123 (value) = *(double*)((ptr) + (offset)); \
1124 if ( poDS->bBigEndian ) \
1125 { \
1126 CPL_MSBPTR64(&(value)); \
1127 } \
1128 else \
1129 { \
1130 CPL_LSBPTR64(&(value)); \
1131 } \
1132 } while(0);
1133
1134 /* -------------------------------------------------------------------- */
1135 /* Read the main header. */
1136 /* -------------------------------------------------------------------- */
1137
1138 {
1139 GByte abyHeader[RMF_HEADER_SIZE];
1140
1141 VSIFSeekL( poDS->fp, 0, SEEK_SET );
1142 VSIFReadL( abyHeader, 1, sizeof(abyHeader), poDS->fp );
1143
1144 if ( memcmp(abyHeader, RMF_SigMTW, sizeof(RMF_SigMTW)) == 0 )
1145 poDS->eRMFType = RMFT_MTW;
1146 else if ( memcmp(abyHeader, RMF_SigRSW_BE, sizeof(RMF_SigRSW_BE)) == 0 )
1147 {
1148 poDS->eRMFType = RMFT_RSW;
1149 poDS->bBigEndian = TRUE;
1150 }
1151 else
1152 poDS->eRMFType = RMFT_RSW;
1153
1154 memcpy( poDS->sHeader.bySignature, abyHeader, RMF_SIGNATURE_SIZE );
1155 RMF_READ_ULONG( abyHeader, poDS->sHeader.iVersion, 4 );
1156 RMF_READ_ULONG( abyHeader, poDS->sHeader.nSize, 8 );
1157 RMF_READ_ULONG( abyHeader, poDS->sHeader.nOvrOffset, 12 );
1158 RMF_READ_ULONG( abyHeader, poDS->sHeader.iUserID, 16 );
1159 memcpy( poDS->sHeader.byName, abyHeader + 20,
1160 sizeof(poDS->sHeader.byName) );
1161 poDS->sHeader.byName[sizeof(poDS->sHeader.byName) - 1] = '\0';
1162 RMF_READ_ULONG( abyHeader, poDS->sHeader.nBitDepth, 52 );
1163 RMF_READ_ULONG( abyHeader, poDS->sHeader.nHeight, 56 );
1164 RMF_READ_ULONG( abyHeader, poDS->sHeader.nWidth, 60 );
1165 RMF_READ_ULONG( abyHeader, poDS->sHeader.nXTiles, 64 );
1166 RMF_READ_ULONG( abyHeader, poDS->sHeader.nYTiles, 68 );
1167 RMF_READ_ULONG( abyHeader, poDS->sHeader.nTileHeight, 72 );
1168 RMF_READ_ULONG( abyHeader, poDS->sHeader.nTileWidth, 76 );
1169 RMF_READ_ULONG( abyHeader, poDS->sHeader.nLastTileHeight, 80 );
1170 RMF_READ_ULONG( abyHeader, poDS->sHeader.nLastTileWidth, 84 );
1171 RMF_READ_ULONG( abyHeader, poDS->sHeader.nROIOffset, 88 );
1172 RMF_READ_ULONG( abyHeader, poDS->sHeader.nROISize, 92 );
1173 RMF_READ_ULONG( abyHeader, poDS->sHeader.nClrTblOffset, 96 );
1174 RMF_READ_ULONG( abyHeader, poDS->sHeader.nClrTblSize, 100 );
1175 RMF_READ_ULONG( abyHeader, poDS->sHeader.nTileTblOffset, 104 );
1176 RMF_READ_ULONG( abyHeader, poDS->sHeader.nTileTblSize, 108 );
1177 RMF_READ_LONG( abyHeader, poDS->sHeader.iMapType, 124 );
1178 RMF_READ_LONG( abyHeader, poDS->sHeader.iProjection, 128 );
1179 RMF_READ_DOUBLE( abyHeader, poDS->sHeader.dfScale, 136 );
1180 RMF_READ_DOUBLE( abyHeader, poDS->sHeader.dfResolution, 144 );
1181 RMF_READ_DOUBLE( abyHeader, poDS->sHeader.dfPixelSize, 152 );
1182 RMF_READ_DOUBLE( abyHeader, poDS->sHeader.dfLLY, 160 );
1183 RMF_READ_DOUBLE( abyHeader, poDS->sHeader.dfLLX, 168 );
1184 RMF_READ_DOUBLE( abyHeader, poDS->sHeader.dfStdP1, 176 );
1185 RMF_READ_DOUBLE( abyHeader, poDS->sHeader.dfStdP2, 184 );
1186 RMF_READ_DOUBLE( abyHeader, poDS->sHeader.dfCenterLong, 192 );
1187 RMF_READ_DOUBLE( abyHeader, poDS->sHeader.dfCenterLat, 200 );
1188 poDS->sHeader.iCompression = *(abyHeader + 208);
1189 poDS->sHeader.iMaskType = *(abyHeader + 209);
1190 poDS->sHeader.iMaskStep = *(abyHeader + 210);
1191 poDS->sHeader.iFrameFlag = *(abyHeader + 211);
1192 RMF_READ_ULONG( abyHeader, poDS->sHeader.nFlagsTblOffset, 212 );
1193 RMF_READ_ULONG( abyHeader, poDS->sHeader.nFlagsTblSize, 216 );
1194 RMF_READ_ULONG( abyHeader, poDS->sHeader.nFileSize0, 220 );
1195 RMF_READ_ULONG( abyHeader, poDS->sHeader.nFileSize1, 224 );
1196 poDS->sHeader.iUnknown = *(abyHeader + 228);
1197 poDS->sHeader.iGeorefFlag = *(abyHeader + 244);
1198 poDS->sHeader.iInverse = *(abyHeader + 245);
1199 memcpy( poDS->sHeader.abyInvisibleColors,
1200 abyHeader + 248, sizeof(poDS->sHeader.abyInvisibleColors) );
1201 RMF_READ_DOUBLE( abyHeader, poDS->sHeader.adfElevMinMax[0], 280 );
1202 RMF_READ_DOUBLE( abyHeader, poDS->sHeader.adfElevMinMax[1], 288 );
1203 RMF_READ_DOUBLE( abyHeader, poDS->sHeader.dfNoData, 296 );
1204 RMF_READ_ULONG( abyHeader, poDS->sHeader.iElevationUnit, 304 );
1205 poDS->sHeader.iElevationType = *(abyHeader + 308);
1206 RMF_READ_ULONG( abyHeader, poDS->sHeader.nExtHdrOffset, 312 );
1207 RMF_READ_ULONG( abyHeader, poDS->sHeader.nExtHdrSize, 316 );
1208 }
1209
1210 /* -------------------------------------------------------------------- */
1211 /* Read the extended header. */
1212 /* -------------------------------------------------------------------- */
1213
1214 if ( poDS->sHeader.nExtHdrOffset && poDS->sHeader.nExtHdrSize )
1215 {
1216 GByte *pabyExtHeader =
1217 (GByte *)VSICalloc( poDS->sHeader.nExtHdrSize, 1 );
1218 if (pabyExtHeader == NULL)
1219 {
1220 delete poDS;
1221 return NULL;
1222 }
1223
1224 VSIFSeekL( poDS->fp, poDS->sHeader.nExtHdrOffset, SEEK_SET );
1225 VSIFReadL( pabyExtHeader, 1, poDS->sHeader.nExtHdrSize, poDS->fp );
1226
1227 RMF_READ_LONG( pabyExtHeader, poDS->sExtHeader.nEllipsoid, 24 );
1228 RMF_READ_LONG( pabyExtHeader, poDS->sExtHeader.nDatum, 32 );
1229 RMF_READ_LONG( pabyExtHeader, poDS->sExtHeader.nZone, 36 );
1230
1231 CPLFree( pabyExtHeader );
1232 }
1233
1234 #undef RMF_READ_DOUBLE
1235 #undef RMF_READ_LONG
1236 #undef RMF_READ_ULONG
1237
1238 #ifdef DEBUG
1239
1240 CPLDebug( "RMF", "%s image has width %d, height %d, bit depth %d, "
1241 "compression scheme %d, %s, nodata %f",
1242 (poDS->eRMFType == RMFT_MTW) ? "MTW" : "RSW",
1243 poDS->sHeader.nWidth, poDS->sHeader.nHeight,
1244 poDS->sHeader.nBitDepth, poDS->sHeader.iCompression,
1245 poDS->bBigEndian ? "big endian" : "little endian",
1246 poDS->sHeader.dfNoData );
1247 CPLDebug( "RMF", "Size %d, offset to overview %#lx, user ID %d, "
1248 "ROI offset %#lx, ROI size %d",
1249 poDS->sHeader.nSize, (unsigned long)poDS->sHeader.nOvrOffset,
1250 poDS->sHeader.iUserID, (unsigned long)poDS->sHeader.nROIOffset,
1251 poDS->sHeader.nROISize );
1252 CPLDebug( "RMF", "Map type %d, projection %d, scale %f, resolution %f, ",
1253 poDS->sHeader.iMapType, poDS->sHeader.iProjection,
1254 poDS->sHeader.dfScale, poDS->sHeader.dfResolution );
1255 CPLDebug( "RMF", "Georeferencing: pixel size %f, LLX %f, LLY %f",
1256 poDS->sHeader.dfPixelSize,
1257 poDS->sHeader.dfLLX, poDS->sHeader.dfLLY );
1258 if ( poDS->sHeader.nROIOffset && poDS->sHeader.nROISize )
1259 {
1260 GUInt32 i;
1261 GInt32 nValue;
1262
1263 CPLDebug( "RMF", "ROI coordinates:" );
1264 for ( i = 0; i < poDS->sHeader.nROISize; i += sizeof(nValue) )
1265 {
1266 GUInt32 nValue;
1267
1268 VSIFSeekL( poDS->fp, poDS->sHeader.nROIOffset + i, SEEK_SET );
1269 VSIFReadL( &nValue, 1, sizeof(nValue), poDS->fp );
1270
1271 CPLDebug( "RMF", "%d", nValue );
1272 }
1273 }
1274 #endif
1275
1276 /* -------------------------------------------------------------------- */
1277 /* Read array of blocks offsets/sizes. */
1278 /* -------------------------------------------------------------------- */
1279 GUInt32 i;
1280
1281 if ( VSIFSeekL( poDS->fp, poDS->sHeader.nTileTblOffset, SEEK_SET ) < 0)
1282 {
1283 delete poDS;
1284 return NULL;
1285 }
1286
1287 poDS->paiTiles = (GUInt32 *)VSIMalloc( poDS->sHeader.nTileTblSize );
1288 if ( !poDS->paiTiles )
1289 {
1290 delete poDS;
1291 return NULL;
1292 }
1293
1294 if ( VSIFReadL( poDS->paiTiles, 1, poDS->sHeader.nTileTblSize,
1295 poDS->fp ) < poDS->sHeader.nTileTblSize )
1296 {
1297 CPLDebug( "RMF", "Can't read tiles offsets/sizes table." );
1298 delete poDS;
1299 return NULL;
1300 }
1301
1302 #ifdef CPL_MSB
1303 if ( !poDS->bBigEndian )
1304 {
1305 for ( i = 0; i < poDS->sHeader.nTileTblSize / sizeof(GUInt32); i++ )
1306 CPL_SWAP32PTR( poDS->paiTiles + i );
1307 }
1308 #else
1309 if ( poDS->bBigEndian )
1310 {
1311 for ( i = 0; i < poDS->sHeader.nTileTblSize / sizeof(GUInt32); i++ )
1312 CPL_SWAP32PTR( poDS->paiTiles + i );
1313 }
1314 #endif
1315
1316 #ifdef DEBUG
1317 CPLDebug( "RMF", "List of block offsets/sizes:" );
1318
1319 for ( i = 0; i < poDS->sHeader.nTileTblSize / sizeof(GUInt32); i += 2 )
1320 {
1321 CPLDebug( "RMF", " %d / %d",
1322 poDS->paiTiles[i], poDS->paiTiles[i + 1] );
1323 }
1324 #endif
1325
1326 /* -------------------------------------------------------------------- */
1327 /* Set up essential image parameters. */
1328 /* -------------------------------------------------------------------- */
1329 GDALDataType eType = GDT_Byte;
1330
1331 poDS->nRasterXSize = poDS->sHeader.nWidth;
1332 poDS->nRasterYSize = poDS->sHeader.nHeight;
1333
1334 if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize))
1335 {
1336 delete poDS;
1337 return NULL;
1338 }
1339
1340 if ( poDS->eRMFType == RMFT_RSW )
1341 {
1342 switch ( poDS->sHeader.nBitDepth )
1343 {
1344 case 32:
1345 case 24:
1346 case 16:
1347 poDS->nBands = 3;
1348 break;
1349 case 1:
1350 case 4:
1351 case 8:
1352 {
1353 // Allocate memory for colour table and read it
1354 poDS->nColorTableSize = 1 << poDS->sHeader.nBitDepth;
1355 if ( poDS->nColorTableSize * 4 > poDS->sHeader.nClrTblSize )
1356 {
1357 CPLDebug( "RMF",
1358 "Wrong color table size. Expected %d, got %d.",
1359 poDS->nColorTableSize * 4,
1360 poDS->sHeader.nClrTblSize );
1361 delete poDS;
1362 return NULL;
1363 }
1364 poDS->pabyColorTable =
1365 (GByte *)VSIMalloc( poDS->sHeader.nClrTblSize );
1366 if (poDS->pabyColorTable == NULL)
1367 {
1368 CPLDebug( "RMF", "Can't allocate color table." );
1369 delete poDS;
1370 return NULL;
1371 }
1372 if ( VSIFSeekL( poDS->fp, poDS->sHeader.nClrTblOffset,
1373 SEEK_SET ) < 0 )
1374 {
1375 CPLDebug( "RMF", "Can't seek to color table location." );
1376 delete poDS;
1377 return NULL;
1378 }
1379 if ( VSIFReadL( poDS->pabyColorTable, 1,
1380 poDS->sHeader.nClrTblSize, poDS->fp )
1381 < poDS->sHeader.nClrTblSize )
1382 {
1383 CPLDebug( "RMF", "Can't read color table." );
1384 delete poDS;
1385 return NULL;
1386 }
1387
1388 GDALColorEntry oEntry;
1389 poDS->poColorTable = new GDALColorTable();
1390 for( i = 0; i < poDS->nColorTableSize; i++ )
1391 {
1392 oEntry.c1 = poDS->pabyColorTable[i * 4]; // Red
1393 oEntry.c2 = poDS->pabyColorTable[i * 4 + 1]; // Green
1394 oEntry.c3 = poDS->pabyColorTable[i * 4 + 2]; // Blue
1395 oEntry.c4 = 255; // Alpha
1396
1397 poDS->poColorTable->SetColorEntry( i, &oEntry );
1398 }
1399 }
1400 poDS->nBands = 1;
1401 break;
1402 default:
1403 break;
1404 }
1405 eType = GDT_Byte;
1406 }
1407 else
1408 {
1409 poDS->nBands = 1;
1410 if ( poDS->sHeader.nBitDepth == 8 )
1411 eType = GDT_Byte;
1412 else if ( poDS->sHeader.nBitDepth == 16 )
1413 eType = GDT_Int16;
1414 else if ( poDS->sHeader.nBitDepth == 32 )
1415 eType = GDT_Int32;
1416 else if ( poDS->sHeader.nBitDepth == 64 )
1417 eType = GDT_Float64;
1418 }
1419
1420 if (poDS->sHeader.nTileWidth == 0 ||
1421 poDS->sHeader.nTileHeight == 0)
1422 {
1423 CPLDebug ("RMF", "Invalid tile dimension : %d x %d",
1424 poDS->sHeader.nTileWidth, poDS->sHeader.nTileHeight);
1425 delete poDS;
1426 return NULL;
1427 }
1428
1429 poDS->nXTiles = ( poDS->nRasterXSize + poDS->sHeader.nTileWidth - 1 ) /
1430 poDS->sHeader.nTileWidth;
1431 poDS->nYTiles = ( poDS->nRasterYSize + poDS->sHeader.nTileHeight - 1 ) /
1432 poDS->sHeader.nTileHeight;
1433
1434 #ifdef DEBUG
1435 CPLDebug( "RMF", "Image is %d tiles wide, %d tiles long",
1436 poDS->nXTiles, poDS->nYTiles );
1437 #endif
1438
1439 /* -------------------------------------------------------------------- */
1440 /* Choose compression scheme. */
1441 /* XXX: The DEM compression method seems to be only applicable */
1442 /* to Int32 data. */
1443 /* -------------------------------------------------------------------- */
1444 if ( poDS->sHeader.iCompression == RMF_COMPRESSION_LZW )
1445 poDS->Decompress = &LZWDecompress;
1446 else if ( poDS->sHeader.iCompression == RMF_COMPRESSION_DEM
1447 && eType == GDT_Int32 )
1448 poDS->Decompress = &DEMDecompress;
1449 else // No compression
1450 poDS->Decompress = NULL;
1451
1452 /* -------------------------------------------------------------------- */
1453 /* Create band information objects. */
1454 /* -------------------------------------------------------------------- */
1455 int iBand;
1456
1457 for( iBand = 1; iBand <= poDS->nBands; iBand++ )
1458 poDS->SetBand( iBand, new RMFRasterBand( poDS, iBand, eType ) );
1459
1460 /* -------------------------------------------------------------------- */
1461 /* Set up projection. */
1462 /* */
1463 /* XXX: If projection value is not specified, but image still have */
1464 /* georeferencing information, assume Gauss-Kruger projection. */
1465 /* -------------------------------------------------------------------- */
1466 if( poDS->sHeader.iProjection > 0 ||
1467 (poDS->sHeader.dfPixelSize != 0.0 &&
1468 poDS->sHeader.dfLLX != 0.0 &&
1469 poDS->sHeader.dfLLY != 0.0) )
1470 {
1471 OGRSpatialReference oSRS;
1472 GInt32 nProj =
1473 (poDS->sHeader.iProjection) ? poDS->sHeader.iProjection : 1L;
1474 double padfPrjParams[8];
1475
1476 padfPrjParams[0] = poDS->sHeader.dfStdP1;
1477 padfPrjParams[1] = poDS->sHeader.dfStdP2;
1478 padfPrjParams[2] = poDS->sHeader.dfCenterLat;
1479 padfPrjParams[3] = poDS->sHeader.dfCenterLong;
1480 padfPrjParams[4] = 1.0;
1481 padfPrjParams[5] = 0.0;
1482 padfPrjParams[6] = 0.0;
1483
1484 // XXX: Compute zone number for Gauss-Kruger (Transverse Mercator)
1485 // projection if it is not specified.
1486 if ( nProj == 1L && poDS->sHeader.dfCenterLong == 0.0 )
1487 {
1488 if ( poDS->sExtHeader.nZone == 0 )
1489 {
1490 double centerXCoord = poDS->sHeader.dfLLX +
1491 (poDS->nRasterXSize * poDS->sHeader.dfPixelSize / 2.0);
1492 padfPrjParams[7] =
1493 floor((centerXCoord - 500000.0 ) / 1000000.0);
1494 }
1495 else
1496 padfPrjParams[7] = poDS->sExtHeader.nZone;
1497 }
1498 else
1499 padfPrjParams[7] = 0.0;
1500
1501 oSRS.importFromPanorama( nProj, poDS->sExtHeader.nDatum,
1502 poDS->sExtHeader.nEllipsoid, padfPrjParams );
1503 if ( poDS->pszProjection )
1504 CPLFree( poDS->pszProjection );
1505 oSRS.exportToWkt( &poDS->pszProjection );
1506 }
1507
1508 /* -------------------------------------------------------------------- */
1509 /* Set up georeferencing. */
1510 /* -------------------------------------------------------------------- */
1511 if ( (poDS->eRMFType == RMFT_RSW && poDS->sHeader.iGeorefFlag) ||
1512 (poDS->eRMFType == RMFT_MTW && poDS->sHeader.dfPixelSize != 0.0) )
1513 {
1514 poDS->adfGeoTransform[0] = poDS->sHeader.dfLLX;
1515 poDS->adfGeoTransform[3] = poDS->sHeader.dfLLY
1516 + poDS->nRasterYSize * poDS->sHeader.dfPixelSize;
1517 poDS->adfGeoTransform[1] = poDS->sHeader.dfPixelSize;
1518 poDS->adfGeoTransform[5] = - poDS->sHeader.dfPixelSize;
1519 poDS->adfGeoTransform[2] = 0.0;
1520 poDS->adfGeoTransform[4] = 0.0;
1521 }
1522
1523 /* -------------------------------------------------------------------- */
1524 /* Set units. */
1525 /* -------------------------------------------------------------------- */
1526
1527 if ( poDS->eRMFType == RMFT_MTW )
1528 {
1529 CPLFree(poDS->pszUnitType);
1530 switch ( poDS->sHeader.iElevationUnit )
1531 {
1532 case 0:
1533 poDS->pszUnitType = CPLStrdup( RMF_UnitsM );
1534 break;
1535 case 1:
1536 poDS->pszUnitType = CPLStrdup( RMF_UnitsCM );
1537 break;
1538 case 2:
1539 poDS->pszUnitType = CPLStrdup( RMF_UnitsDM );
1540 break;
1541 case 3:
1542 poDS->pszUnitType = CPLStrdup( RMF_UnitsMM );
1543 break;
1544 default:
1545 poDS->pszUnitType = CPLStrdup( RMF_UnitsEmpty );
1546 break;
1547 }
1548 }
1549
1550 /* -------------------------------------------------------------------- */
1551 /* Report some other dataset related information. */
1552 /* -------------------------------------------------------------------- */
1553
1554 if ( poDS->eRMFType == RMFT_MTW )
1555 {
1556 char szTemp[256];
1557
1558 snprintf( szTemp, sizeof(szTemp), "%g", poDS->sHeader.adfElevMinMax[0] );
1559 poDS->SetMetadataItem( "ELEVATION_MINIMUM", szTemp );
1560
1561 snprintf( szTemp, sizeof(szTemp), "%g", poDS->sHeader.adfElevMinMax[1] );
1562 poDS->SetMetadataItem( "ELEVATION_MAXIMUM", szTemp );
1563
1564 poDS->SetMetadataItem( "ELEVATION_UNITS", poDS->pszUnitType );
1565
1566 snprintf( szTemp, sizeof(szTemp), "%d", poDS->sHeader.iElevationType );
1567 poDS->SetMetadataItem( "ELEVATION_TYPE", szTemp );
1568 }
1569
1570 /* -------------------------------------------------------------------- */
1571 /* Check for overviews. */
1572 /* -------------------------------------------------------------------- */
1573 poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
1574
1575 return( poDS );
1576 }
1577
1578 /************************************************************************/
1579 /* Create() */
1580 /************************************************************************/
1581
Create(const char * pszFilename,int nXSize,int nYSize,int nBands,GDALDataType eType,char ** papszParmList)1582 GDALDataset *RMFDataset::Create( const char * pszFilename,
1583 int nXSize, int nYSize, int nBands,
1584 GDALDataType eType, char **papszParmList )
1585
1586 {
1587 if ( nBands != 1 && nBands != 3 )
1588 {
1589 CPLError( CE_Failure, CPLE_NotSupported,
1590 "RMF driver doesn't support %d bands. Must be 1 or 3.\n",
1591 nBands );
1592
1593 return NULL;
1594 }
1595
1596 if ( nBands == 1
1597 && eType != GDT_Byte
1598 && eType != GDT_Int16
1599 && eType != GDT_Int32
1600 && eType != GDT_Float64 )
1601 {
1602 CPLError( CE_Failure, CPLE_AppDefined,
1603 "Attempt to create RMF dataset with an illegal data type (%s),\n"
1604 "only Byte, Int16, Int32 and Float64 types supported "
1605 "by the format for single-band images.\n",
1606 GDALGetDataTypeName(eType) );
1607
1608 return NULL;
1609 }
1610
1611 if ( nBands == 3 && eType != GDT_Byte )
1612 {
1613 CPLError( CE_Failure, CPLE_AppDefined,
1614 "Attempt to create RMF dataset with an illegal data type (%s),\n"
1615 "only Byte type supported by the format for three-band images.\n",
1616 GDALGetDataTypeName(eType) );
1617
1618 return NULL;
1619 }
1620
1621 /* -------------------------------------------------------------------- */
1622 /* Create the dataset. */
1623 /* -------------------------------------------------------------------- */
1624 RMFDataset *poDS;
1625
1626 poDS = new RMFDataset();
1627
1628 poDS->fp = VSIFOpenL( pszFilename, "w+b" );
1629 if( poDS->fp == NULL )
1630 {
1631 CPLError( CE_Failure, CPLE_OpenFailed, "Unable to create file %s.\n",
1632 pszFilename );
1633 delete poDS;
1634 return NULL;
1635 }
1636
1637 poDS->pszFilename = pszFilename;
1638
1639 /* -------------------------------------------------------------------- */
1640 /* Fill the RMFHeader */
1641 /* -------------------------------------------------------------------- */
1642 GUInt32 nTileSize, nCurPtr = 0;
1643 GUInt32 nBlockXSize =
1644 ( nXSize < RMF_DEFAULT_BLOCKXSIZE ) ? nXSize : RMF_DEFAULT_BLOCKXSIZE;
1645 GUInt32 nBlockYSize =
1646 ( nYSize < RMF_DEFAULT_BLOCKYSIZE ) ? nYSize : RMF_DEFAULT_BLOCKYSIZE;
1647 const char *pszValue;
1648
1649 if ( CSLFetchBoolean( papszParmList, "MTW", FALSE) )
1650 poDS->eRMFType = RMFT_MTW;
1651 else
1652 poDS->eRMFType = RMFT_RSW;
1653 if ( poDS->eRMFType == RMFT_MTW )
1654 memcpy( poDS->sHeader.bySignature, RMF_SigMTW, RMF_SIGNATURE_SIZE );
1655 else
1656 memcpy( poDS->sHeader.bySignature, RMF_SigRSW, RMF_SIGNATURE_SIZE );
1657 poDS->sHeader.iVersion = 0x0200;
1658 poDS->sHeader.nOvrOffset = 0x00;
1659 poDS->sHeader.iUserID = 0x00;
1660 memset( poDS->sHeader.byName, 0, sizeof(poDS->sHeader.byName) );
1661 poDS->sHeader.nBitDepth = GDALGetDataTypeSize( eType ) * nBands;
1662 poDS->sHeader.nHeight = nYSize;
1663 poDS->sHeader.nWidth = nXSize;
1664
1665 pszValue = CSLFetchNameValue(papszParmList,"BLOCKXSIZE");
1666 if( pszValue != NULL )
1667 nBlockXSize = atoi( pszValue );
1668
1669 pszValue = CSLFetchNameValue(papszParmList,"BLOCKYSIZE");
1670 if( pszValue != NULL )
1671 nBlockYSize = atoi( pszValue );
1672
1673 poDS->sHeader.nTileWidth = nBlockXSize;
1674 poDS->sHeader.nTileHeight = nBlockYSize;
1675
1676 poDS->nXTiles = poDS->sHeader.nXTiles =
1677 ( nXSize + poDS->sHeader.nTileWidth - 1 ) / poDS->sHeader.nTileWidth;
1678 poDS->nYTiles = poDS->sHeader.nYTiles =
1679 ( nYSize + poDS->sHeader.nTileHeight - 1 ) / poDS->sHeader.nTileHeight;
1680 poDS->sHeader.nLastTileHeight = nYSize % poDS->sHeader.nTileHeight;
1681 if ( !poDS->sHeader.nLastTileHeight )
1682 poDS->sHeader.nLastTileHeight = poDS->sHeader.nTileHeight;
1683 poDS->sHeader.nLastTileWidth = nXSize % poDS->sHeader.nTileWidth;
1684 if ( !poDS->sHeader.nLastTileWidth )
1685 poDS->sHeader.nLastTileWidth = poDS->sHeader.nTileWidth;
1686
1687 poDS->sHeader.nROIOffset = 0x00;
1688 poDS->sHeader.nROISize = 0x00;
1689
1690 nCurPtr += RMF_HEADER_SIZE;
1691
1692 // Extended header
1693 poDS->sHeader.nExtHdrOffset = nCurPtr;
1694 poDS->sHeader.nExtHdrSize = RMF_EXT_HEADER_SIZE;
1695 nCurPtr += poDS->sHeader.nExtHdrSize;
1696
1697 // Color table
1698 if ( poDS->eRMFType == RMFT_RSW && nBands == 1 )
1699 {
1700 GUInt32 i;
1701
1702 if ( poDS->sHeader.nBitDepth > 8 )
1703 {
1704 CPLError( CE_Failure, CPLE_AppDefined,
1705 "Cannot create color table of RSW with nBitDepth = %d. Retry with MTW ?",
1706 poDS->sHeader.nBitDepth );
1707 delete poDS;
1708 return NULL;
1709 }
1710
1711 poDS->sHeader.nClrTblOffset = nCurPtr;
1712 poDS->nColorTableSize = 1 << poDS->sHeader.nBitDepth;
1713 poDS->sHeader.nClrTblSize = poDS->nColorTableSize * 4;
1714 poDS->pabyColorTable = (GByte *) VSIMalloc( poDS->sHeader.nClrTblSize );
1715 if (poDS->pabyColorTable == NULL)
1716 {
1717 CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
1718 delete poDS;
1719 return NULL;
1720 }
1721 for ( i = 0; i < poDS->nColorTableSize; i++ )
1722 {
1723 poDS->pabyColorTable[i * 4] =
1724 poDS->pabyColorTable[i * 4 + 1] =
1725 poDS->pabyColorTable[i * 4 + 2] = (GByte) i;
1726 poDS->pabyColorTable[i * 4 + 3] = 0;
1727 }
1728 nCurPtr += poDS->sHeader.nClrTblSize;
1729 }
1730 else
1731 {
1732 poDS->sHeader.nClrTblOffset = 0x00;
1733 poDS->sHeader.nClrTblSize = 0x00;
1734 }
1735
1736 // Blocks table
1737 poDS->sHeader.nTileTblOffset = nCurPtr;
1738 poDS->sHeader.nTileTblSize =
1739 poDS->sHeader.nXTiles * poDS->sHeader.nYTiles * 4 * 2;
1740 poDS->paiTiles = (GUInt32 *)CPLCalloc( poDS->sHeader.nTileTblSize, 1 );
1741 nCurPtr += poDS->sHeader.nTileTblSize;
1742 nTileSize = poDS->sHeader.nTileWidth * poDS->sHeader.nTileHeight
1743 * GDALGetDataTypeSize( eType ) / 8;
1744 poDS->sHeader.nSize =
1745 poDS->paiTiles[poDS->sHeader.nTileTblSize / 4 - 2] + nTileSize;
1746
1747 // Elevation units
1748 if ( EQUAL(poDS->pszUnitType, RMF_UnitsM) )
1749 poDS->sHeader.iElevationUnit = 0;
1750 else if ( EQUAL(poDS->pszUnitType, RMF_UnitsCM) )
1751 poDS->sHeader.iElevationUnit = 1;
1752 else if ( EQUAL(poDS->pszUnitType, RMF_UnitsDM) )
1753 poDS->sHeader.iElevationUnit = 2;
1754 else if ( EQUAL(poDS->pszUnitType, RMF_UnitsMM) )
1755 poDS->sHeader.iElevationUnit = 3;
1756 else
1757 poDS->sHeader.iElevationUnit = 0;
1758
1759 poDS->sHeader.iMapType = -1;
1760 poDS->sHeader.iProjection = -1;
1761 poDS->sHeader.dfScale = 10000.0;
1762 poDS->sHeader.dfResolution = 100.0;
1763 poDS->sHeader.iCompression = 0;
1764 poDS->sHeader.iMaskType = 0;
1765 poDS->sHeader.iMaskStep = 0;
1766 poDS->sHeader.iFrameFlag = 0;
1767 poDS->sHeader.nFlagsTblOffset = 0x00;
1768 poDS->sHeader.nFlagsTblSize = 0x00;
1769 poDS->sHeader.nFileSize0 = 0x00;
1770 poDS->sHeader.nFileSize1 = 0x00;
1771 poDS->sHeader.iUnknown = 0;
1772 poDS->sHeader.iGeorefFlag = 0;
1773 poDS->sHeader.iInverse = 0;
1774 memset( poDS->sHeader.abyInvisibleColors, 0,
1775 sizeof(poDS->sHeader.abyInvisibleColors) );
1776 poDS->sHeader.adfElevMinMax[0] = 0.0;
1777 poDS->sHeader.adfElevMinMax[1] = 0.0;
1778 poDS->sHeader.dfNoData = 0.0;
1779 poDS->sHeader.iElevationType = 0;
1780
1781 poDS->nRasterXSize = nXSize;
1782 poDS->nRasterYSize = nYSize;
1783 poDS->eAccess = GA_Update;
1784 poDS->nBands = nBands;
1785
1786 poDS->WriteHeader();
1787
1788 /* -------------------------------------------------------------------- */
1789 /* Create band information objects. */
1790 /* -------------------------------------------------------------------- */
1791 int iBand;
1792
1793 for( iBand = 1; iBand <= poDS->nBands; iBand++ )
1794 poDS->SetBand( iBand, new RMFRasterBand( poDS, iBand, eType ) );
1795
1796 return (GDALDataset *) poDS;
1797 }
1798
1799 /************************************************************************/
1800 /* GDALRegister_RMF() */
1801 /************************************************************************/
1802
GDALRegister_RMF()1803 void GDALRegister_RMF()
1804
1805 {
1806 GDALDriver *poDriver;
1807
1808 if( GDALGetDriverByName( "RMF" ) == NULL )
1809 {
1810 poDriver = new GDALDriver();
1811
1812 poDriver->SetDescription( "RMF" );
1813 poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
1814 poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
1815 "Raster Matrix Format" );
1816 poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
1817 "frmt_rmf.html" );
1818 poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "rsw" );
1819 poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
1820 "Byte Int16 Int32 Float64" );
1821 poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
1822 "<CreationOptionList>"
1823 " <Option name='MTW' type='boolean' description='Create MTW DEM matrix'/>"
1824 " <Option name='BLOCKXSIZE' type='int' description='Tile Width'/>"
1825 " <Option name='BLOCKYSIZE' type='int' description='Tile Height'/>"
1826 "</CreationOptionList>" );
1827 poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
1828
1829 poDriver->pfnIdentify = RMFDataset::Identify;
1830 poDriver->pfnOpen = RMFDataset::Open;
1831 poDriver->pfnCreate = RMFDataset::Create;
1832
1833 GetGDALDriverManager()->RegisterDriver( poDriver );
1834 }
1835 }
1836
1837