1 : /******************************************************************************
2 : * $Id: elasdataset.cpp 23048 2011-09-04 17:05:50Z rouault $
3 : *
4 : * Project: ELAS Translator
5 : * Purpose: Complete implementation of ELAS translator module for GDAL.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 1999, Frank Warmerdam
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "gdal_pam.h"
31 :
32 : CPL_CVSID("$Id: elasdataset.cpp 23048 2011-09-04 17:05:50Z rouault $");
33 :
34 : CPL_C_START
35 : void GDALRegister_ELAS(void);
36 : CPL_C_END
37 :
38 : typedef struct {
39 : GInt32 NBIH; /* bytes in header, normaly 1024 */
40 : GInt32 NBPR; /* bytes per data record (all bands of scanline) */
41 : GInt32 IL; /* initial line - normally 1 */
42 : GInt32 LL; /* last line */
43 : GInt32 IE; /* initial element (pixel), normally 1 */
44 : GInt32 LE; /* last element (pixel) */
45 : GInt32 NC; /* number of channels (bands) */
46 : GInt32 H4321; /* header record identifier - always 4321. */
47 : char YLabel[4]; /* Should be "NOR" for UTM */
48 : GInt32 YOffset;/* topleft pixel center northing */
49 : char XLabel[4]; /* Should be "EAS" for UTM */
50 : GInt32 XOffset;/* topleft pixel center easting */
51 : float YPixSize;/* height of pixel in georef units */
52 : float XPixSize;/* width of pixel in georef units */
53 : float Matrix[4]; /* 2x2 transformation matrix. Should be
54 : 1,0,0,1 for pixel/line, or
55 : 1,0,0,-1 for UTM */
56 : GByte IH19[4];/* data type, and size flags */
57 : GInt32 IH20; /* number of secondary headers */
58 : char unused1[8];
59 : GInt32 LABL; /* used by LABL module */
60 : char HEAD; /* used by HEAD module */
61 : char Comment1[64];
62 : char Comment2[64];
63 : char Comment3[64];
64 : char Comment4[64];
65 : char Comment5[64];
66 : char Comment6[64];
67 : GUInt16 ColorTable[256]; /* RGB packed with 4 bits each */
68 : char unused2[32];
69 : } ELASHeader;
70 :
71 :
72 : /************************************************************************/
73 : /* ==================================================================== */
74 : /* ELASDataset */
75 : /* ==================================================================== */
76 : /************************************************************************/
77 :
78 : class ELASRasterBand;
79 :
80 : class ELASDataset : public GDALPamDataset
81 : {
82 : friend class ELASRasterBand;
83 :
84 : VSILFILE *fp;
85 :
86 : ELASHeader sHeader;
87 : int bHeaderModified;
88 :
89 : GDALDataType eRasterDataType;
90 :
91 : int nLineOffset;
92 : int nBandOffset; // within a line.
93 :
94 : double adfGeoTransform[6];
95 :
96 : public:
97 : ELASDataset();
98 : ~ELASDataset();
99 :
100 : virtual CPLErr GetGeoTransform( double * );
101 : virtual CPLErr SetGeoTransform( double * );
102 :
103 : static GDALDataset *Open( GDALOpenInfo * );
104 : static int Identify( GDALOpenInfo * );
105 : static GDALDataset *Create( const char * pszFilename,
106 : int nXSize, int nYSize, int nBands,
107 : GDALDataType eType, char ** papszParmList );
108 :
109 : virtual void FlushCache( void );
110 : };
111 :
112 : /************************************************************************/
113 : /* ==================================================================== */
114 : /* ELASRasterBand */
115 : /* ==================================================================== */
116 : /************************************************************************/
117 :
118 : class ELASRasterBand : public GDALPamRasterBand
119 68 : {
120 : friend class ELASDataset;
121 :
122 : public:
123 :
124 : ELASRasterBand( ELASDataset *, int );
125 :
126 : // should override RasterIO eventually.
127 :
128 : virtual CPLErr IReadBlock( int, int, void * );
129 : virtual CPLErr IWriteBlock( int, int, void * );
130 : };
131 :
132 :
133 : /************************************************************************/
134 : /* ELASRasterBand() */
135 : /************************************************************************/
136 :
137 68 : ELASRasterBand::ELASRasterBand( ELASDataset *poDS, int nBand )
138 :
139 : {
140 68 : this->poDS = poDS;
141 68 : this->nBand = nBand;
142 :
143 68 : this->eAccess = poDS->eAccess;
144 :
145 68 : eDataType = poDS->eRasterDataType;
146 :
147 68 : nBlockXSize = poDS->GetRasterXSize();
148 68 : nBlockYSize = 1;
149 68 : }
150 :
151 : /************************************************************************/
152 : /* IReadBlock() */
153 : /************************************************************************/
154 :
155 60 : CPLErr ELASRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
156 : void * pImage )
157 :
158 : {
159 60 : ELASDataset *poGDS = (ELASDataset *) poDS;
160 60 : CPLErr eErr = CE_None;
161 : long nOffset;
162 : int nDataSize;
163 :
164 60 : CPLAssert( nBlockXOff == 0 );
165 :
166 60 : nDataSize = GDALGetDataTypeSize(eDataType) * poGDS->GetRasterXSize() / 8;
167 60 : nOffset = poGDS->nLineOffset * nBlockYOff + 1024 + (nBand-1) * nDataSize;
168 :
169 : /* -------------------------------------------------------------------- */
170 : /* If we can't seek to the data, we will assume this is a newly */
171 : /* created file, and that the file hasn't been extended yet. */
172 : /* Just read as zeros. */
173 : /* -------------------------------------------------------------------- */
174 60 : if( VSIFSeekL( poGDS->fp, nOffset, SEEK_SET ) != 0
175 : || VSIFReadL( pImage, 1, nDataSize, poGDS->fp ) != (size_t) nDataSize )
176 : {
177 : CPLError( CE_Failure, CPLE_FileIO,
178 : "Seek or read of %d bytes at %ld failed.\n",
179 0 : nDataSize, nOffset );
180 0 : eErr = CE_Failure;
181 : }
182 :
183 60 : return eErr;
184 : }
185 :
186 : /************************************************************************/
187 : /* IWriteBlock() */
188 : /************************************************************************/
189 :
190 190 : CPLErr ELASRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
191 : void * pImage )
192 :
193 : {
194 190 : ELASDataset *poGDS = (ELASDataset *) poDS;
195 190 : CPLErr eErr = CE_None;
196 : long nOffset;
197 : int nDataSize;
198 :
199 190 : CPLAssert( nBlockXOff == 0 );
200 190 : CPLAssert( eAccess == GA_Update );
201 :
202 190 : nDataSize = GDALGetDataTypeSize(eDataType) * poGDS->GetRasterXSize() / 8;
203 190 : nOffset = poGDS->nLineOffset * nBlockYOff + 1024 + (nBand-1) * nDataSize;
204 :
205 190 : if( VSIFSeekL( poGDS->fp, nOffset, SEEK_SET ) != 0
206 : || VSIFWriteL( pImage, 1, nDataSize, poGDS->fp ) != (size_t) nDataSize )
207 : {
208 : CPLError( CE_Failure, CPLE_FileIO,
209 : "Seek or write of %d bytes at %ld failed.\n",
210 0 : nDataSize, nOffset );
211 0 : eErr = CE_Failure;
212 : }
213 :
214 190 : return eErr;
215 : }
216 :
217 : /************************************************************************/
218 : /* ==================================================================== */
219 : /* ELASDataset */
220 : /* ==================================================================== */
221 : /************************************************************************/
222 :
223 :
224 : /************************************************************************/
225 : /* ELASDataset() */
226 : /************************************************************************/
227 :
228 30 : ELASDataset::ELASDataset()
229 :
230 : {
231 30 : fp = NULL;
232 :
233 30 : adfGeoTransform[0] = 0.0;
234 30 : adfGeoTransform[1] = 1.0;
235 30 : adfGeoTransform[2] = 0.0;
236 30 : adfGeoTransform[3] = 0.0;
237 30 : adfGeoTransform[4] = 0.0;
238 30 : adfGeoTransform[5] = 1.0;
239 30 : }
240 :
241 : /************************************************************************/
242 : /* ~ELASDataset() */
243 : /************************************************************************/
244 :
245 30 : ELASDataset::~ELASDataset()
246 :
247 : {
248 30 : FlushCache();
249 :
250 30 : if( fp != NULL )
251 : {
252 30 : VSIFCloseL( fp );
253 30 : fp = NULL;
254 : }
255 30 : }
256 :
257 : /************************************************************************/
258 : /* FlushCache() */
259 : /* */
260 : /* We also write out the header, if it is modified. */
261 : /************************************************************************/
262 :
263 30 : void ELASDataset::FlushCache()
264 :
265 : {
266 30 : GDALDataset::FlushCache();
267 :
268 30 : if( bHeaderModified )
269 : {
270 16 : VSIFSeekL( fp, 0, SEEK_SET );
271 16 : VSIFWriteL( &sHeader, 1024, 1, fp );
272 16 : bHeaderModified = FALSE;
273 : }
274 30 : }
275 :
276 : /************************************************************************/
277 : /* Identify() */
278 : /************************************************************************/
279 :
280 12897 : int ELASDataset::Identify( GDALOpenInfo * poOpenInfo )
281 :
282 : {
283 : /* -------------------------------------------------------------------- */
284 : /* First we check to see if the file has the expected header */
285 : /* bytes. */
286 : /* -------------------------------------------------------------------- */
287 12897 : if( poOpenInfo->nHeaderBytes < 256 )
288 11106 : return FALSE;
289 :
290 1791 : if( CPL_MSBWORD32(*((GInt32 *) (poOpenInfo->pabyHeader+0))) != 1024
291 : || CPL_MSBWORD32(*((GInt32 *) (poOpenInfo->pabyHeader+28))) != 4321 )
292 : {
293 1761 : return FALSE;
294 : }
295 :
296 30 : return TRUE;
297 : }
298 :
299 : /************************************************************************/
300 : /* Open() */
301 : /************************************************************************/
302 :
303 3618 : GDALDataset *ELASDataset::Open( GDALOpenInfo * poOpenInfo )
304 :
305 : {
306 3618 : if( !Identify(poOpenInfo) )
307 3588 : return NULL;
308 :
309 : /* -------------------------------------------------------------------- */
310 : /* Create a corresponding GDALDataset. */
311 : /* -------------------------------------------------------------------- */
312 : ELASDataset *poDS;
313 : const char *pszAccess;
314 :
315 30 : if( poOpenInfo->eAccess == GA_Update )
316 17 : pszAccess = "r+b";
317 : else
318 13 : pszAccess = "rb";
319 :
320 30 : poDS = new ELASDataset();
321 :
322 30 : poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, pszAccess );
323 30 : if( poDS->fp == NULL )
324 : {
325 : CPLError( CE_Failure, CPLE_OpenFailed,
326 : "Attempt to open `%s' with acces `%s' failed.\n",
327 0 : poOpenInfo->pszFilename, pszAccess );
328 0 : delete poDS;
329 0 : return NULL;
330 : }
331 :
332 30 : poDS->eAccess = poOpenInfo->eAccess;
333 :
334 : /* -------------------------------------------------------------------- */
335 : /* Read the header information. */
336 : /* -------------------------------------------------------------------- */
337 30 : poDS->bHeaderModified = FALSE;
338 30 : if( VSIFReadL( &(poDS->sHeader), 1024, 1, poDS->fp ) != 1 )
339 : {
340 : CPLError( CE_Failure, CPLE_FileIO,
341 : "Attempt to read 1024 byte header filed on file %s\n",
342 0 : poOpenInfo->pszFilename );
343 0 : return NULL;
344 : }
345 :
346 : /* -------------------------------------------------------------------- */
347 : /* Extract information of interest from the header. */
348 : /* -------------------------------------------------------------------- */
349 : int nStart, nEnd, nELASDataType, nBytesPerSample;
350 :
351 30 : poDS->nLineOffset = CPL_MSBWORD32( poDS->sHeader.NBPR );
352 :
353 30 : nStart = CPL_MSBWORD32( poDS->sHeader.IL );
354 30 : nEnd = CPL_MSBWORD32( poDS->sHeader.LL );
355 30 : poDS->nRasterYSize = nEnd - nStart + 1;
356 :
357 30 : nStart = CPL_MSBWORD32( poDS->sHeader.IE );
358 30 : nEnd = CPL_MSBWORD32( poDS->sHeader.LE );
359 30 : poDS->nRasterXSize = nEnd - nStart + 1;
360 :
361 30 : poDS->nBands = CPL_MSBWORD32( poDS->sHeader.NC );
362 :
363 30 : if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) ||
364 : !GDALCheckBandCount(poDS->nBands, FALSE))
365 : {
366 0 : delete poDS;
367 0 : return NULL;
368 : }
369 :
370 30 : nELASDataType = (poDS->sHeader.IH19[2] & 0x7e) >> 2;
371 30 : nBytesPerSample = poDS->sHeader.IH19[3];
372 :
373 30 : if( nELASDataType == 0 && nBytesPerSample == 1 )
374 0 : poDS->eRasterDataType = GDT_Byte;
375 50 : else if( nELASDataType == 1 && nBytesPerSample == 1 )
376 20 : poDS->eRasterDataType = GDT_Byte;
377 15 : else if( nELASDataType == 16 && nBytesPerSample == 4 )
378 5 : poDS->eRasterDataType = GDT_Float32;
379 10 : else if( nELASDataType == 17 && nBytesPerSample == 8 )
380 5 : poDS->eRasterDataType = GDT_Float64;
381 : else
382 : {
383 0 : delete poDS;
384 : CPLError( CE_Failure, CPLE_AppDefined,
385 : "Unrecognised image data type %d, with BytesPerSample=%d.\n",
386 0 : nELASDataType, nBytesPerSample );
387 0 : return NULL;
388 : }
389 :
390 : /* -------------------------------------------------------------------- */
391 : /* Band offsets are always multiples of 256 within a multi-band */
392 : /* scanline of data. */
393 : /* -------------------------------------------------------------------- */
394 : poDS->nBandOffset =
395 30 : (poDS->nRasterXSize * GDALGetDataTypeSize(poDS->eRasterDataType)/8);
396 :
397 30 : if( poDS->nBandOffset % 256 != 0 )
398 : {
399 : poDS->nBandOffset =
400 30 : poDS->nBandOffset - (poDS->nBandOffset % 256) + 256;
401 : }
402 :
403 : /* -------------------------------------------------------------------- */
404 : /* Create band information objects. */
405 : /* -------------------------------------------------------------------- */
406 : int iBand;
407 :
408 196 : for( iBand = 0; iBand < poDS->nBands; iBand++ )
409 : {
410 68 : poDS->SetBand( iBand+1, new ELASRasterBand( poDS, iBand+1 ) );
411 : }
412 :
413 : /* -------------------------------------------------------------------- */
414 : /* Extract the projection coordinates, if present. */
415 : /* -------------------------------------------------------------------- */
416 30 : if( poDS->sHeader.XOffset != 0 )
417 : {
418 11 : CPL_MSBPTR32(&(poDS->sHeader.XPixSize));
419 11 : CPL_MSBPTR32(&(poDS->sHeader.YPixSize));
420 :
421 : poDS->adfGeoTransform[0] =
422 11 : (GInt32) CPL_MSBWORD32(poDS->sHeader.XOffset);
423 11 : poDS->adfGeoTransform[1] = poDS->sHeader.XPixSize;
424 11 : poDS->adfGeoTransform[2] = 0.0;
425 : poDS->adfGeoTransform[3] =
426 11 : (GInt32) CPL_MSBWORD32(poDS->sHeader.YOffset);
427 11 : poDS->adfGeoTransform[4] = 0.0;
428 11 : poDS->adfGeoTransform[5] = -1.0 * ABS(poDS->sHeader.YPixSize);
429 :
430 11 : CPL_MSBPTR32(&(poDS->sHeader.XPixSize));
431 11 : CPL_MSBPTR32(&(poDS->sHeader.YPixSize));
432 :
433 11 : poDS->adfGeoTransform[0] -= poDS->adfGeoTransform[1] * 0.5;
434 11 : poDS->adfGeoTransform[3] -= poDS->adfGeoTransform[5] * 0.5;
435 : }
436 : else
437 : {
438 19 : poDS->adfGeoTransform[0] = 0.0;
439 19 : poDS->adfGeoTransform[1] = 1.0;
440 19 : poDS->adfGeoTransform[2] = 0.0;
441 19 : poDS->adfGeoTransform[3] = 0.0;
442 19 : poDS->adfGeoTransform[4] = 0.0;
443 19 : poDS->adfGeoTransform[5] = 1.0;
444 : }
445 :
446 : /* -------------------------------------------------------------------- */
447 : /* Initialize any PAM information. */
448 : /* -------------------------------------------------------------------- */
449 30 : poDS->SetDescription( poOpenInfo->pszFilename );
450 30 : poDS->TryLoadXML();
451 :
452 : /* -------------------------------------------------------------------- */
453 : /* Check for external overviews. */
454 : /* -------------------------------------------------------------------- */
455 30 : poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
456 :
457 30 : return( poDS );
458 : }
459 :
460 : /************************************************************************/
461 : /* Create() */
462 : /* */
463 : /* Create a new GeoTIFF or TIFF file. */
464 : /************************************************************************/
465 :
466 44 : GDALDataset *ELASDataset::Create( const char * pszFilename,
467 : int nXSize, int nYSize, int nBands,
468 : GDALDataType eType,
469 : char ** /* notdef: papszParmList */ )
470 :
471 : {
472 : int nBandOffset;
473 :
474 : /* -------------------------------------------------------------------- */
475 : /* Verify input options. */
476 : /* -------------------------------------------------------------------- */
477 44 : if (nBands <= 0)
478 : {
479 : CPLError( CE_Failure, CPLE_NotSupported,
480 1 : "ELAS driver does not support %d bands.\n", nBands);
481 1 : return NULL;
482 : }
483 :
484 43 : if( eType != GDT_Byte && eType != GDT_Float32 && eType != GDT_Float64 )
485 : {
486 : CPLError( CE_Failure, CPLE_AppDefined,
487 : "Attempt to create an ELAS dataset with an illegal\n"
488 : "data type (%d).\n",
489 24 : eType );
490 :
491 24 : return NULL;
492 : }
493 :
494 : /* -------------------------------------------------------------------- */
495 : /* Try to create the file. */
496 : /* -------------------------------------------------------------------- */
497 : FILE *fp;
498 :
499 19 : fp = VSIFOpen( pszFilename, "w" );
500 :
501 19 : if( fp == NULL )
502 : {
503 : CPLError( CE_Failure, CPLE_OpenFailed,
504 : "Attempt to create file `%s' failed.\n",
505 2 : pszFilename );
506 2 : return NULL;
507 : }
508 :
509 : /* -------------------------------------------------------------------- */
510 : /* How long will each band of a scanline be? */
511 : /* -------------------------------------------------------------------- */
512 17 : nBandOffset = nXSize * GDALGetDataTypeSize(eType)/8;
513 :
514 17 : if( nBandOffset % 256 != 0 )
515 : {
516 17 : nBandOffset = nBandOffset - (nBandOffset % 256) + 256;
517 : }
518 :
519 : /* -------------------------------------------------------------------- */
520 : /* Setup header data block. */
521 : /* */
522 : /* Note that CPL_MSBWORD32() will swap little endian words to */
523 : /* big endian on little endian platforms. */
524 : /* -------------------------------------------------------------------- */
525 : ELASHeader sHeader;
526 :
527 17 : memset( &sHeader, 0, 1024 );
528 :
529 17 : sHeader.NBIH = CPL_MSBWORD32(1024);
530 :
531 17 : sHeader.NBPR = CPL_MSBWORD32(nBands * nBandOffset);
532 :
533 17 : sHeader.IL = CPL_MSBWORD32(1);
534 17 : sHeader.LL = CPL_MSBWORD32(nYSize);
535 :
536 17 : sHeader.IE = CPL_MSBWORD32(1);
537 17 : sHeader.LE = CPL_MSBWORD32(nXSize);
538 :
539 17 : sHeader.NC = CPL_MSBWORD32(nBands);
540 :
541 17 : sHeader.H4321 = CPL_MSBWORD32(4321);
542 :
543 17 : sHeader.IH19[0] = 0x04;
544 17 : sHeader.IH19[1] = 0xd2;
545 17 : sHeader.IH19[3] = (GByte) (GDALGetDataTypeSize(eType) / 8);
546 :
547 17 : if( eType == GDT_Byte )
548 11 : sHeader.IH19[2] = 1 << 2;
549 6 : else if( eType == GDT_Float32 )
550 3 : sHeader.IH19[2] = 16 << 2;
551 3 : else if( eType == GDT_Float64 )
552 3 : sHeader.IH19[2] = 17 << 2;
553 :
554 : /* -------------------------------------------------------------------- */
555 : /* Write the header data. */
556 : /* -------------------------------------------------------------------- */
557 17 : VSIFWrite( &sHeader, 1024, 1, fp );
558 :
559 : /* -------------------------------------------------------------------- */
560 : /* Now write out zero data for all the imagery. This is */
561 : /* inefficient, but simplies the IReadBlock() / IWriteBlock() logic.*/
562 : /* -------------------------------------------------------------------- */
563 : GByte *pabyLine;
564 :
565 17 : pabyLine = (GByte *) CPLCalloc(nBandOffset,nBands);
566 1007 : for( int iLine = 0; iLine < nYSize; iLine++ )
567 : {
568 990 : if( VSIFWrite( pabyLine, 1, nBandOffset, fp ) != (size_t) nBandOffset )
569 : {
570 : CPLError( CE_Failure, CPLE_FileIO,
571 : "Error writing ELAS image data ... likely insufficient"
572 0 : " disk space.\n" );
573 0 : VSIFClose( fp );
574 0 : CPLFree( pabyLine );
575 0 : return NULL;
576 : }
577 : }
578 :
579 17 : CPLFree( pabyLine );
580 :
581 17 : VSIFClose( fp );
582 :
583 : /* -------------------------------------------------------------------- */
584 : /* Try to return a regular handle on the file. */
585 : /* -------------------------------------------------------------------- */
586 17 : return (GDALDataset *) GDALOpen( pszFilename, GA_Update );
587 : }
588 :
589 : /************************************************************************/
590 : /* GetGeoTransform() */
591 : /************************************************************************/
592 :
593 9 : CPLErr ELASDataset::GetGeoTransform( double * padfTransform )
594 :
595 : {
596 9 : memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
597 :
598 9 : return( CE_None );
599 : }
600 :
601 : /************************************************************************/
602 : /* SetGeoTransform() */
603 : /************************************************************************/
604 :
605 16 : CPLErr ELASDataset::SetGeoTransform( double * padfTransform )
606 :
607 : {
608 : /* -------------------------------------------------------------------- */
609 : /* I don't think it supports rotation, but perhaps it is possible */
610 : /* for us to use the 2x2 transform matrix to accomplish some */
611 : /* sort of rotation. */
612 : /* -------------------------------------------------------------------- */
613 16 : if( padfTransform[2] != 0.0 || padfTransform[4] != 0.0 )
614 : {
615 : CPLError( CE_Failure, CPLE_AppDefined,
616 : "Attempt to set rotated geotransform on ELAS file.\n"
617 0 : "ELAS does not support rotation.\n" );
618 :
619 0 : return CE_Failure;
620 : }
621 :
622 : /* -------------------------------------------------------------------- */
623 : /* Remember the new transform, and update the header. */
624 : /* -------------------------------------------------------------------- */
625 : int nXOff, nYOff;
626 :
627 16 : memcpy( adfGeoTransform, padfTransform, sizeof(double)*6 );
628 :
629 16 : bHeaderModified = TRUE;
630 :
631 16 : nXOff = (int) (adfGeoTransform[0] + adfGeoTransform[1]*0.5);
632 16 : nYOff = (int) (adfGeoTransform[3] + adfGeoTransform[5]*0.5);
633 :
634 16 : sHeader.XOffset = CPL_MSBWORD32(nXOff);
635 16 : sHeader.YOffset = CPL_MSBWORD32(nYOff);
636 :
637 16 : sHeader.XPixSize = (float) ABS(adfGeoTransform[1]);
638 16 : sHeader.YPixSize = (float) ABS(adfGeoTransform[5]);
639 :
640 16 : CPL_MSBPTR32(&(sHeader.XPixSize));
641 16 : CPL_MSBPTR32(&(sHeader.YPixSize));
642 :
643 16 : strncpy( sHeader.YLabel, "NOR ", 4 );
644 16 : strncpy( sHeader.XLabel, "EAS ", 4 );
645 :
646 16 : sHeader.Matrix[0] = 1.0;
647 16 : sHeader.Matrix[1] = 0.0;
648 16 : sHeader.Matrix[2] = 0.0;
649 16 : sHeader.Matrix[3] = -1.0;
650 :
651 16 : CPL_MSBPTR32(&(sHeader.Matrix[0]));
652 16 : CPL_MSBPTR32(&(sHeader.Matrix[1]));
653 16 : CPL_MSBPTR32(&(sHeader.Matrix[2]));
654 16 : CPL_MSBPTR32(&(sHeader.Matrix[3]));
655 :
656 16 : return( CE_None );
657 : }
658 :
659 :
660 : /************************************************************************/
661 : /* GDALRegister_ELAS() */
662 : /************************************************************************/
663 :
664 558 : void GDALRegister_ELAS()
665 :
666 : {
667 : GDALDriver *poDriver;
668 :
669 558 : if( GDALGetDriverByName( "ELAS" ) == NULL )
670 : {
671 537 : poDriver = new GDALDriver();
672 :
673 537 : poDriver->SetDescription( "ELAS" );
674 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
675 537 : "ELAS" );
676 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
677 537 : "Byte Float32 Float64" );
678 :
679 537 : poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
680 :
681 537 : poDriver->pfnOpen = ELASDataset::Open;
682 537 : poDriver->pfnIdentify = ELASDataset::Identify;
683 537 : poDriver->pfnCreate = ELASDataset::Create;
684 :
685 537 : GetGDALDriverManager()->RegisterDriver( poDriver );
686 : }
687 558 : }
|