1 : /*****************************************************************************
2 : * $Id: IntergraphDataset.cpp 25785 2013-03-23 11:34:53Z rouault $
3 : *
4 : * Project: Intergraph Raster Format support
5 : * Purpose: Read/Write Intergraph Raster Format, dataset support
6 : * Author: Ivan Lucena, ivan.lucena@pmldnet.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2007, Ivan Lucena
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_priv.h"
31 : #include "cpl_conv.h"
32 : #include "cpl_string.h"
33 : #include "cpl_csv.h"
34 : #include "ogr_spatialref.h"
35 : #include "gdal_pam.h"
36 : #include "gdal_alg.h"
37 :
38 : #include "IntergraphDataset.h"
39 : #include "IntergraphBand.h"
40 : #include "IngrTypes.h"
41 :
42 : // ----------------------------------------------------------------------------
43 : // IntergraphDataset::IntergraphDataset()
44 : // ----------------------------------------------------------------------------
45 :
46 77 : IntergraphDataset::IntergraphDataset()
47 : {
48 77 : pszFilename = NULL;
49 77 : fp = NULL;
50 :
51 77 : adfGeoTransform[0] = 0.0;
52 77 : adfGeoTransform[1] = 1.0;
53 77 : adfGeoTransform[2] = 0.0;
54 77 : adfGeoTransform[3] = 0.0;
55 77 : adfGeoTransform[4] = 0.0;
56 77 : adfGeoTransform[5] = 1.0;
57 :
58 77 : hVirtual.poDS = NULL;
59 77 : hVirtual.poBand = NULL;
60 77 : hVirtual.pszFileName = NULL;
61 :
62 77 : memset(&hHeaderOne, 0, sizeof(hHeaderOne));
63 77 : memset(&hHeaderTwo, 0, sizeof(hHeaderTwo));
64 77 : }
65 :
66 : // ----------------------------------------------------------------------------
67 : // IntergraphDataset::~IntergraphDataset()
68 : // ----------------------------------------------------------------------------
69 :
70 77 : IntergraphDataset::~IntergraphDataset()
71 : {
72 77 : FlushCache();
73 :
74 77 : CPLFree( pszFilename );
75 :
76 77 : if( fp != NULL )
77 : {
78 77 : VSIFCloseL( fp );
79 : }
80 77 : }
81 :
82 : // ----------------------------------------------------------------------------
83 : // IntergraphDataset::Open()
84 : // ----------------------------------------------------------------------------
85 :
86 12613 : GDALDataset *IntergraphDataset::Open( GDALOpenInfo *poOpenInfo )
87 : {
88 12613 : if( poOpenInfo->nHeaderBytes < 1024 )
89 : {
90 11881 : return NULL;
91 : }
92 :
93 : // --------------------------------------------------------------------
94 : // Assign Header Information
95 : // --------------------------------------------------------------------
96 :
97 : INGR_HeaderOne hHeaderOne;
98 :
99 732 : INGR_HeaderOneDiskToMem( &hHeaderOne, (GByte*) poOpenInfo->pabyHeader);
100 :
101 : // --------------------------------------------------------------------
102 : // Check Header Type (HTC) Version
103 : // --------------------------------------------------------------------
104 :
105 732 : if( hHeaderOne.HeaderType.Version != INGR_HEADER_VERSION )
106 : {
107 629 : return NULL;
108 : }
109 :
110 : // --------------------------------------------------------------------
111 : // Check Header Type (HTC) 2D / 3D Flag
112 : // --------------------------------------------------------------------
113 :
114 103 : if( ( hHeaderOne.HeaderType.Is2Dor3D != INGR_HEADER_2D ) &&
115 : ( hHeaderOne.HeaderType.Is2Dor3D != INGR_HEADER_3D ) )
116 : {
117 26 : return NULL;
118 : }
119 :
120 : // --------------------------------------------------------------------
121 : // Check Header Type (HTC) Type Flag
122 : // --------------------------------------------------------------------
123 :
124 77 : if( hHeaderOne.HeaderType.Type != INGR_HEADER_TYPE )
125 : {
126 0 : return NULL;
127 : }
128 :
129 : // --------------------------------------------------------------------
130 : // Check Grid File Version (VER)
131 : // --------------------------------------------------------------------
132 :
133 77 : if( hHeaderOne.GridFileVersion != 1 &&
134 : hHeaderOne.GridFileVersion != 2 &&
135 : hHeaderOne.GridFileVersion != 3 )
136 : {
137 0 : return NULL;
138 : }
139 :
140 : // --------------------------------------------------------------------
141 : // Check Words To Follow (WTC) Minimum Value
142 : // --------------------------------------------------------------------
143 :
144 77 : if( hHeaderOne.WordsToFollow < 254 )
145 : {
146 0 : return NULL;
147 : }
148 :
149 : // --------------------------------------------------------------------
150 : // Check Words To Follow (WTC) Integrity
151 : // --------------------------------------------------------------------
152 :
153 77 : float fHeaderBlocks = (float) ( hHeaderOne.WordsToFollow + 2 ) / 256;
154 :
155 77 : if( ( fHeaderBlocks - (int) fHeaderBlocks ) != 0.0 )
156 : {
157 0 : return NULL;
158 : }
159 :
160 : // --------------------------------------------------------------------
161 : // Get Data Type Code (DTC) => Format Type
162 : // --------------------------------------------------------------------
163 :
164 77 : INGR_Format eFormat = (INGR_Format) hHeaderOne.DataTypeCode;
165 :
166 : // --------------------------------------------------------------------
167 : // We need to scan around the file, so we open it now.
168 : // --------------------------------------------------------------------
169 :
170 : VSILFILE *fp;
171 :
172 77 : if( poOpenInfo->eAccess == GA_ReadOnly )
173 : {
174 44 : fp = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
175 : }
176 : else
177 : {
178 33 : fp = VSIFOpenL( poOpenInfo->pszFilename, "r+b" );
179 : }
180 :
181 77 : if( fp == NULL )
182 : {
183 0 : CPLError( CE_Failure, CPLE_OpenFailed, "%s", VSIStrerror( errno ) );
184 0 : return NULL;
185 : }
186 :
187 : // --------------------------------------------------------------------
188 : // Get Format Type from the tile directory
189 : // --------------------------------------------------------------------
190 :
191 77 : if( hHeaderOne.DataTypeCode == TiledRasterData )
192 : {
193 : INGR_TileHeader hTileDir;
194 :
195 3 : int nOffset = 2 + ( 2 * ( hHeaderOne.WordsToFollow + 1 ) );
196 :
197 : GByte abyBuffer[SIZEOF_TDIR];
198 :
199 3 : if( (VSIFSeekL( fp, nOffset, SEEK_SET ) == -1 ) ||
200 : (VSIFReadL( abyBuffer, 1, SIZEOF_TDIR, fp ) == 0) )
201 : {
202 0 : VSIFCloseL( fp );
203 : CPLError( CE_Failure, CPLE_AppDefined,
204 0 : "Error reading tiles header" );
205 0 : return NULL;
206 : }
207 :
208 3 : INGR_TileHeaderDiskToMem( &hTileDir, abyBuffer );
209 :
210 3 : if( !
211 : ( hTileDir.ApplicationType == 1 &&
212 : hTileDir.SubTypeCode == 7 &&
213 : ( hTileDir.WordsToFollow % 4 ) == 0 &&
214 : hTileDir.PacketVersion == 1 &&
215 : hTileDir.Identifier == 1 ) )
216 : {
217 : CPLError( CE_Failure, CPLE_AppDefined,
218 0 : "Cannot recognize tiles header info");
219 0 : VSIFCloseL( fp );
220 0 : return NULL;
221 : }
222 :
223 3 : eFormat = (INGR_Format) hTileDir.DataTypeCode;
224 : }
225 :
226 : // --------------------------------------------------------------------
227 : // Check Scannable Flag
228 : // --------------------------------------------------------------------
229 : /*
230 : if (hHeaderOne.ScannableFlag == HasLineHeader)
231 : {
232 : CPLError( CE_Failure, CPLE_AppDefined,
233 : "Intergraph Raster Scannable Line Header not supported yet" );
234 : VSIFCloseL( fp );
235 : return NULL;
236 : }
237 : */
238 : // --------------------------------------------------------------------
239 : // Check supported Format Type
240 : // --------------------------------------------------------------------
241 :
242 77 : if( eFormat != ByteInteger &&
243 : eFormat != WordIntegers &&
244 : eFormat != Integers32Bit &&
245 : eFormat != FloatingPoint32Bit &&
246 : eFormat != FloatingPoint64Bit &&
247 : eFormat != RunLengthEncoded &&
248 : eFormat != RunLengthEncodedC &&
249 : eFormat != CCITTGroup4 &&
250 : eFormat != AdaptiveRGB &&
251 : eFormat != Uncompressed24bit &&
252 : eFormat != AdaptiveGrayScale &&
253 : eFormat != ContinuousTone &&
254 : eFormat != JPEGGRAY &&
255 : eFormat != JPEGRGB &&
256 : eFormat != JPEGCYMK )
257 : {
258 : CPLError( CE_Failure, CPLE_AppDefined,
259 : "Intergraph Raster Format %d ( \"%s\" ) not supported",
260 0 : hHeaderOne.DataTypeCode, INGR_GetFormatName( (uint16) eFormat ) );
261 0 : VSIFCloseL( fp );
262 0 : return NULL;
263 : }
264 :
265 : // -----------------------------------------------------------------
266 : // Create a corresponding GDALDataset
267 : // -----------------------------------------------------------------
268 :
269 : IntergraphDataset *poDS;
270 :
271 77 : poDS = new IntergraphDataset();
272 77 : poDS->eAccess = poOpenInfo->eAccess;
273 77 : poDS->pszFilename = CPLStrdup( poOpenInfo->pszFilename );
274 77 : poDS->fp = fp;
275 :
276 : // --------------------------------------------------------------------
277 : // Get X Size from Pixels Per Line (PPL)
278 : // --------------------------------------------------------------------
279 :
280 77 : poDS->nRasterXSize = hHeaderOne.PixelsPerLine;
281 :
282 : // --------------------------------------------------------------------
283 : // Get Y Size from Number of Lines (NOL)
284 : // --------------------------------------------------------------------
285 :
286 77 : poDS->nRasterYSize = hHeaderOne.NumberOfLines;
287 :
288 154 : if (poDS->nRasterXSize <= 0 || poDS->nRasterYSize <= 0)
289 : {
290 : CPLError( CE_Failure, CPLE_AppDefined,
291 : "Invalid dimensions : %d x %d",
292 0 : poDS->nRasterXSize, poDS->nRasterYSize);
293 0 : delete poDS;
294 0 : return NULL;
295 : }
296 :
297 : // --------------------------------------------------------------------
298 : // Get Geo Transformation from Homogeneous Transformation Matrix (TRN)
299 : // --------------------------------------------------------------------
300 :
301 77 : INGR_GetTransMatrix( &hHeaderOne, poDS->adfGeoTransform );
302 :
303 : // --------------------------------------------------------------------
304 : // Set Metadata Information
305 : // --------------------------------------------------------------------
306 :
307 : poDS->SetMetadataItem( "VERSION",
308 77 : CPLSPrintf ( "%d", hHeaderOne.GridFileVersion ), "IMAGE_STRUCTURE" );
309 : poDS->SetMetadataItem( "RESOLUTION",
310 77 : CPLSPrintf ( "%d", (hHeaderOne.DeviceResolution < 0)?-hHeaderOne.DeviceResolution:1) );
311 :
312 : // --------------------------------------------------------------------
313 : // Create Band Information
314 : // --------------------------------------------------------------------
315 :
316 77 : int nBands = 0;
317 77 : int nBandOffset = 0;
318 :
319 : GByte abyBuf[MAX(SIZEOF_HDR1,SIZEOF_HDR2_A)];
320 :
321 77 : do
322 : {
323 77 : VSIFSeekL( poDS->fp, nBandOffset, SEEK_SET );
324 :
325 77 : VSIFReadL( abyBuf, 1, SIZEOF_HDR1, poDS->fp );
326 :
327 77 : INGR_HeaderOneDiskToMem( &poDS->hHeaderOne, abyBuf );
328 :
329 77 : VSIFReadL( abyBuf, 1, SIZEOF_HDR2_A, poDS->fp );
330 :
331 77 : INGR_HeaderTwoADiskToMem( &poDS->hHeaderTwo, abyBuf );
332 :
333 77 : switch( eFormat )
334 : {
335 : case JPEGRGB:
336 : case JPEGCYMK:
337 : {
338 : IntergraphBitmapBand* poBand;
339 1 : nBands++;
340 : poDS->SetBand( nBands,
341 1 : poBand = new IntergraphBitmapBand( poDS, nBands, nBandOffset, 1 ));
342 1 : if (poBand->pabyBMPBlock == NULL)
343 : {
344 0 : delete poDS;
345 0 : return NULL;
346 : }
347 1 : nBands++;
348 : poDS->SetBand( nBands,
349 1 : poBand = new IntergraphBitmapBand( poDS, nBands, nBandOffset, 2 ));
350 1 : if (poBand->pabyBMPBlock == NULL)
351 : {
352 0 : delete poDS;
353 0 : return NULL;
354 : }
355 1 : nBands++;
356 : poDS->SetBand( nBands,
357 1 : poBand = new IntergraphBitmapBand( poDS, nBands, nBandOffset, 3 ));
358 1 : if (poBand->pabyBMPBlock == NULL)
359 : {
360 0 : delete poDS;
361 0 : return NULL;
362 : }
363 1 : break;
364 : }
365 : case JPEGGRAY:
366 : case CCITTGroup4:
367 : {
368 : IntergraphBitmapBand* poBand;
369 2 : nBands++;
370 : poDS->SetBand( nBands,
371 2 : poBand = new IntergraphBitmapBand( poDS, nBands, nBandOffset ));
372 2 : if (poBand->pabyBMPBlock == NULL)
373 : {
374 0 : delete poDS;
375 0 : return NULL;
376 : }
377 2 : break;
378 : }
379 : case RunLengthEncoded:
380 : case RunLengthEncodedC:
381 : case AdaptiveGrayScale:
382 : {
383 : IntergraphRLEBand* poBand;
384 8 : nBands++;
385 : poDS->SetBand( nBands,
386 8 : poBand = new IntergraphRLEBand( poDS, nBands, nBandOffset ));
387 16 : if (poBand->pabyBlockBuf == NULL || poBand->pabyRLEBlock == NULL)
388 : {
389 0 : delete poDS;
390 0 : return NULL;
391 : }
392 8 : break;
393 : }
394 : case AdaptiveRGB:
395 : case ContinuousTone:
396 : {
397 : IntergraphRLEBand* poBand;
398 1 : nBands++;
399 : poDS->SetBand( nBands,
400 1 : poBand = new IntergraphRLEBand( poDS, nBands, nBandOffset, 1 ));
401 2 : if (poBand->pabyBlockBuf == NULL || poBand->pabyRLEBlock == NULL)
402 : {
403 0 : delete poDS;
404 0 : return NULL;
405 : }
406 1 : nBands++;
407 : poDS->SetBand( nBands,
408 1 : poBand = new IntergraphRLEBand( poDS, nBands, nBandOffset, 2 ));
409 2 : if (poBand->pabyBlockBuf == NULL || poBand->pabyRLEBlock == NULL)
410 : {
411 0 : delete poDS;
412 0 : return NULL;
413 : }
414 1 : nBands++;
415 : poDS->SetBand( nBands,
416 1 : poBand = new IntergraphRLEBand( poDS, nBands, nBandOffset, 3 ));
417 2 : if (poBand->pabyBlockBuf == NULL || poBand->pabyRLEBlock == NULL)
418 : {
419 0 : delete poDS;
420 0 : return NULL;
421 : }
422 1 : break;
423 : }
424 : case Uncompressed24bit:
425 : {
426 : IntergraphRGBBand* poBand;
427 5 : nBands++;
428 : poDS->SetBand( nBands,
429 5 : poBand = new IntergraphRGBBand( poDS, nBands, nBandOffset, 1 ));
430 5 : if (poBand->pabyBlockBuf == NULL)
431 : {
432 0 : delete poDS;
433 0 : return NULL;
434 : }
435 5 : nBands++;
436 : poDS->SetBand( nBands,
437 5 : poBand = new IntergraphRGBBand( poDS, nBands, nBandOffset, 2 ));
438 5 : if (poBand->pabyBlockBuf == NULL)
439 : {
440 0 : delete poDS;
441 0 : return NULL;
442 : }
443 5 : nBands++;
444 : poDS->SetBand( nBands,
445 5 : poBand = new IntergraphRGBBand( poDS, nBands, nBandOffset, 3 ));
446 5 : if (poBand->pabyBlockBuf == NULL)
447 : {
448 0 : delete poDS;
449 0 : return NULL;
450 : }
451 5 : break;
452 : }
453 : default:
454 : {
455 : IntergraphRasterBand* poBand;
456 60 : nBands++;
457 : poDS->SetBand( nBands,
458 60 : poBand = new IntergraphRasterBand( poDS, nBands, nBandOffset ));
459 60 : if (poBand->pabyBlockBuf == NULL)
460 : {
461 0 : delete poDS;
462 0 : return NULL;
463 : }
464 : }
465 : }
466 :
467 : // ----------------------------------------------------------------
468 : // Get next band offset from Catenated File Pointer (CFP)
469 : // ----------------------------------------------------------------
470 :
471 77 : nBandOffset = poDS->hHeaderTwo.CatenatedFilePointer;
472 : }
473 : while( nBandOffset != 0 );
474 :
475 77 : poDS->nBands = nBands;
476 :
477 : // --------------------------------------------------------------------
478 : // Initialize any PAM information
479 : // --------------------------------------------------------------------
480 :
481 77 : poDS->SetDescription( poOpenInfo->pszFilename );
482 77 : poDS->TryLoadXML();
483 :
484 : /* -------------------------------------------------------------------- */
485 : /* Check for external overviews. */
486 : /* -------------------------------------------------------------------- */
487 :
488 77 : poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
489 :
490 77 : return ( poDS );
491 : }
492 :
493 : // ----------------------------------------------------------------------------
494 : // IntergraphDataset::Create()
495 : // ----------------------------------------------------------------------------
496 :
497 47 : GDALDataset *IntergraphDataset::Create( const char *pszFilename,
498 : int nXSize,
499 : int nYSize,
500 : int nBands,
501 : GDALDataType eType,
502 : char **papszOptions )
503 : {
504 47 : int nDeviceResolution = 1;
505 : const char *pszValue;
506 47 : const char *pszCompression = NULL;
507 :
508 47 : pszValue = CSLFetchNameValue(papszOptions, "RESOLUTION");
509 47 : if( pszValue != NULL )
510 2 : nDeviceResolution = -atoi( pszValue );
511 :
512 47 : char *pszExtension = CPLStrlwr(CPLStrdup(CPLGetExtension(pszFilename)));
513 47 : if ( EQUAL( pszExtension, "rle" ) )
514 1 : pszCompression = INGR_GetFormatName(RunLengthEncoded);
515 47 : CPLFree(pszExtension);
516 :
517 47 : if( eType != GDT_Byte &&
518 : eType != GDT_Int16 &&
519 : eType != GDT_Int32 &&
520 : eType != GDT_UInt16 &&
521 : eType != GDT_UInt32 &&
522 : eType != GDT_Float32&&
523 : eType != GDT_Float64 )
524 : {
525 : CPLError( CE_Failure, CPLE_AppDefined, "Data type not supported (%s)",
526 12 : GDALGetDataTypeName( eType ) );
527 12 : return NULL;
528 : }
529 :
530 : // --------------------------------------------------------------------
531 : // Fill headers with minimun information
532 : // --------------------------------------------------------------------
533 :
534 : INGR_HeaderOne hHdr1;
535 : INGR_HeaderTwoA hHdr2;
536 : INGR_ColorTable256 hCTab;
537 : int i;
538 :
539 35 : memset(&hHdr1, 0, SIZEOF_HDR1);
540 35 : memset(&hHdr2, 0, SIZEOF_HDR2_A);
541 35 : memset(&hCTab, 0, SIZEOF_CTAB);
542 :
543 35 : hHdr1.HeaderType.Version = INGR_HEADER_VERSION;
544 35 : hHdr1.HeaderType.Type = INGR_HEADER_TYPE;
545 35 : hHdr1.HeaderType.Is2Dor3D = INGR_HEADER_2D;
546 35 : hHdr1.DataTypeCode = (uint16) INGR_GetFormat( eType, (pszCompression!=NULL)?pszCompression:"None" );
547 35 : hHdr1.WordsToFollow = ( ( SIZEOF_HDR1 * 3 ) / 2 ) - 2;
548 35 : hHdr1.ApplicationType = GenericRasterImageFile;
549 35 : hHdr1.XViewOrigin = 0.0;
550 35 : hHdr1.YViewOrigin = 0.0;
551 35 : hHdr1.ZViewOrigin = 0.0;
552 35 : hHdr1.XViewExtent = 0.0;
553 35 : hHdr1.YViewExtent = 0.0;
554 35 : hHdr1.ZViewExtent = 0.0;
555 560 : for( i = 0; i < 15; i++ )
556 525 : hHdr1.TransformationMatrix[i] = 0.0;
557 35 : hHdr1.TransformationMatrix[15] = 1.0;
558 35 : hHdr1.PixelsPerLine = nXSize;
559 35 : hHdr1.NumberOfLines = nYSize;
560 35 : hHdr1.DeviceResolution = nDeviceResolution;
561 35 : hHdr1.ScanlineOrientation = UpperLeftHorizontal;
562 35 : hHdr1.ScannableFlag = NoLineHeader;
563 35 : hHdr1.RotationAngle = 0.0;
564 35 : hHdr1.SkewAngle = 0.0;
565 35 : hHdr1.DataTypeModifier = 0;
566 35 : hHdr1.DesignFileName[0] = '\0';
567 35 : hHdr1.DataBaseFileName[0] = '\0';
568 35 : hHdr1.ParentGridFileName[0] = '\0';
569 35 : hHdr1.FileDescription[0] = '\0';
570 35 : hHdr1.Minimum = INGR_SetMinMax( eType, 0.0 );
571 35 : hHdr1.Maximum = INGR_SetMinMax( eType, 0.0 );
572 35 : hHdr1.GridFileVersion = 3;
573 35 : hHdr1.Reserved[0] = 0;
574 35 : hHdr1.Reserved[1] = 0;
575 35 : hHdr1.Reserved[2] = 0;
576 35 : hHdr2.Gain = 0;
577 35 : hHdr2.OffsetThreshold = 0;
578 35 : hHdr2.View1 = 0;
579 35 : hHdr2.View2 = 0;
580 35 : hHdr2.ViewNumber = 0;
581 35 : hHdr2.Reserved2 = 0;
582 35 : hHdr2.Reserved3 = 0;
583 35 : hHdr2.AspectRatio = nXSize / nYSize;
584 35 : hHdr2.CatenatedFilePointer = 0;
585 35 : hHdr2.ColorTableType = NoColorTable;
586 35 : hHdr2.NumberOfCTEntries = 0;
587 35 : hHdr2.Reserved8 = 0;
588 3885 : for( i = 0; i < 110; i++ )
589 3850 : hHdr2.Reserved[i] = 0;
590 35 : hHdr2.ApplicationPacketLength = 0;
591 35 : hHdr2.ApplicationPacketPointer = 0;
592 :
593 : // --------------------------------------------------------------------
594 : // RGB Composite assumption
595 : // --------------------------------------------------------------------
596 :
597 35 : if( eType == GDT_Byte &&
598 : nBands == 3 )
599 : {
600 2 : hHdr1.DataTypeCode = Uncompressed24bit;
601 : }
602 :
603 : // --------------------------------------------------------------------
604 : // Create output file with minimum header info
605 : // --------------------------------------------------------------------
606 :
607 35 : VSILFILE *fp = VSIFOpenL( pszFilename, "wb+" );
608 :
609 35 : if( fp == NULL )
610 : {
611 : CPLError( CE_Failure, CPLE_OpenFailed,
612 2 : "Attempt to create file %s' failed.\n", pszFilename );
613 2 : return NULL;
614 : }
615 :
616 : GByte abyBuf[MAX(SIZEOF_HDR1,SIZEOF_CTAB)];
617 :
618 33 : INGR_HeaderOneMemToDisk( &hHdr1, abyBuf );
619 :
620 33 : VSIFWriteL( abyBuf, 1, SIZEOF_HDR1, fp );
621 :
622 33 : INGR_HeaderTwoAMemToDisk( &hHdr2, abyBuf );
623 :
624 33 : VSIFWriteL( abyBuf, 1, SIZEOF_HDR2_A, fp );
625 :
626 33 : unsigned int n = 0;
627 :
628 8481 : for( i = 0; i < 256; i++ )
629 : {
630 8448 : STRC2BUF( abyBuf, n, hCTab.Entry[i].v_red );
631 8448 : STRC2BUF( abyBuf, n, hCTab.Entry[i].v_green );
632 8448 : STRC2BUF( abyBuf, n, hCTab.Entry[i].v_blue );
633 : }
634 :
635 33 : VSIFWriteL( abyBuf, 1, SIZEOF_CTAB, fp );
636 :
637 33 : VSIFCloseL( fp );
638 :
639 : // --------------------------------------------------------------------
640 : // Returns a new IntergraphDataset from the created file
641 : // --------------------------------------------------------------------
642 :
643 33 : return ( IntergraphDataset * ) GDALOpen( pszFilename, GA_Update );
644 : }
645 :
646 : // ----------------------------------------------------------------------------
647 : // IntergraphDataset::CreateCopy()
648 : // ----------------------------------------------------------------------------
649 :
650 20 : GDALDataset *IntergraphDataset::CreateCopy( const char *pszFilename,
651 : GDALDataset *poSrcDS,
652 : int bStrict,
653 : char **papszOptions,
654 : GDALProgressFunc pfnProgress,
655 : void *pProgressData )
656 : {
657 : (void) bStrict;
658 :
659 20 : int nBands = poSrcDS->GetRasterCount();
660 20 : if (nBands == 0)
661 : {
662 : CPLError( CE_Failure, CPLE_NotSupported,
663 1 : "Intergraph driver does not support source dataset with zero band.\n");
664 1 : return NULL;
665 : }
666 :
667 19 : if( !pfnProgress( 0.0, NULL, pProgressData ) )
668 : {
669 0 : return NULL;
670 : }
671 :
672 : // --------------------------------------------------------------------
673 : // Query GDAL Data Type
674 : // --------------------------------------------------------------------
675 :
676 19 : GDALDataType eType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
677 :
678 : // --------------------------------------------------------------------
679 : // Copy metadata
680 : // --------------------------------------------------------------------
681 :
682 19 : char **papszCreateOptions = CSLDuplicate( papszOptions );
683 : const char *pszValue;
684 :
685 19 : pszValue = CSLFetchNameValue(papszCreateOptions, "RESOLUTION");
686 19 : if( pszValue == NULL )
687 : {
688 19 : const char *value = poSrcDS->GetMetadataItem("RESOLUTION");
689 19 : if (value)
690 : {
691 : papszCreateOptions = CSLSetNameValue( papszCreateOptions, "RESOLUTION",
692 2 : value );
693 : }
694 : }
695 :
696 : // --------------------------------------------------------------------
697 : // Create IntergraphDataset
698 : // --------------------------------------------------------------------
699 :
700 : IntergraphDataset *poDstDS;
701 :
702 : poDstDS = (IntergraphDataset*) IntergraphDataset::Create( pszFilename,
703 : poSrcDS->GetRasterXSize(),
704 : poSrcDS->GetRasterYSize(),
705 : poSrcDS->GetRasterCount(),
706 : eType,
707 19 : papszCreateOptions );
708 :
709 19 : CSLDestroy( papszCreateOptions );
710 :
711 19 : if( poDstDS == NULL )
712 : {
713 6 : return NULL;
714 : }
715 :
716 : // --------------------------------------------------------------------
717 : // Copy Transformation Matrix to the dataset
718 : // --------------------------------------------------------------------
719 :
720 : double adfGeoTransform[6];
721 :
722 13 : poDstDS->SetProjection( poSrcDS->GetProjectionRef() );
723 13 : poSrcDS->GetGeoTransform( adfGeoTransform );
724 13 : poDstDS->SetGeoTransform( adfGeoTransform );
725 :
726 : // --------------------------------------------------------------------
727 : // Copy information to the raster band
728 : // --------------------------------------------------------------------
729 :
730 : GDALRasterBand *poSrcBand;
731 : GDALRasterBand *poDstBand;
732 : double dfMin;
733 : double dfMax;
734 : double dfMean;
735 13 : double dfStdDev = -1;
736 :
737 28 : for( int i = 1; i <= poDstDS->nBands; i++)
738 : {
739 15 : delete poDstDS->GetRasterBand(i);
740 : }
741 13 : poDstDS->nBands = 0;
742 :
743 13 : if( poDstDS->hHeaderOne.DataTypeCode == Uncompressed24bit )
744 : {
745 1 : poDstDS->SetBand( 1, new IntergraphRGBBand( poDstDS, 1, 0, 3 ) );
746 2 : poDstDS->SetBand( 2, new IntergraphRGBBand( poDstDS, 2, 0, 2 ) );
747 2 : poDstDS->SetBand( 3, new IntergraphRGBBand( poDstDS, 3, 0, 1 ) );
748 1 : poDstDS->nBands = 3;
749 : }
750 : else
751 : {
752 64 : for( int i = 1; i <= poSrcDS->GetRasterCount(); i++ )
753 : {
754 20 : poSrcBand = poSrcDS->GetRasterBand(i);
755 20 : eType = poSrcDS->GetRasterBand(i)->GetRasterDataType();
756 :
757 20 : poDstBand = new IntergraphRasterBand( poDstDS, i, 0, eType );
758 20 : poDstDS->SetBand( i, poDstBand );
759 :
760 20 : poDstBand->SetCategoryNames( poSrcBand->GetCategoryNames() );
761 20 : poDstBand->SetColorTable( poSrcBand->GetColorTable() );
762 20 : poSrcBand->GetStatistics( false, true, &dfMin, &dfMax, &dfMean, &dfStdDev );
763 20 : poDstBand->SetStatistics( dfMin, dfMax, dfMean, dfStdDev );
764 : }
765 : }
766 :
767 : // --------------------------------------------------------------------
768 : // Copy image data
769 : // --------------------------------------------------------------------
770 :
771 13 : int nXSize = poDstDS->GetRasterXSize();
772 13 : int nYSize = poDstDS->GetRasterYSize();
773 :
774 : int nBlockXSize;
775 : int nBlockYSize;
776 :
777 13 : CPLErr eErr = CE_None;
778 :
779 36 : for( int iBand = 1; iBand <= poSrcDS->GetRasterCount(); iBand++ )
780 : {
781 23 : GDALRasterBand *poDstBand = poDstDS->GetRasterBand( iBand );
782 23 : GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( iBand );
783 :
784 : // ------------------------------------------------------------
785 : // Copy Untiled / Uncompressed
786 : // ------------------------------------------------------------
787 :
788 : int iYOffset, iXOffset;
789 : void *pData;
790 :
791 23 : poSrcBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
792 :
793 23 : nBlockXSize = nXSize;
794 23 : nBlockYSize = 1;
795 :
796 23 : pData = CPLMalloc( nBlockXSize * nBlockYSize * GDALGetDataTypeSize( eType ) / 8 );
797 :
798 518 : for( iYOffset = 0; iYOffset < nYSize; iYOffset += nBlockYSize )
799 : {
800 990 : for( iXOffset = 0; iXOffset < nXSize; iXOffset += nBlockXSize )
801 : {
802 : eErr = poSrcBand->RasterIO( GF_Read,
803 : iXOffset, iYOffset,
804 : nBlockXSize, nBlockYSize,
805 : pData, nBlockXSize, nBlockYSize,
806 495 : eType, 0, 0 );
807 495 : if( eErr != CE_None )
808 : {
809 0 : return NULL;
810 : }
811 : eErr = poDstBand->RasterIO( GF_Write,
812 : iXOffset, iYOffset,
813 : nBlockXSize, nBlockYSize,
814 : pData, nBlockXSize, nBlockYSize,
815 495 : eType, 0, 0 );
816 495 : if( eErr != CE_None )
817 : {
818 0 : return NULL;
819 : }
820 : }
821 495 : if( ( eErr == CE_None ) && ( ! pfnProgress(
822 : ( iYOffset + 1 ) / ( double ) nYSize, NULL, pProgressData ) ) )
823 : {
824 0 : eErr = CE_Failure;
825 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated CreateCopy()" );
826 : }
827 : }
828 23 : CPLFree( pData );
829 : }
830 :
831 : // --------------------------------------------------------------------
832 : // Finalize
833 : // --------------------------------------------------------------------
834 :
835 13 : poDstDS->FlushCache();
836 :
837 13 : return poDstDS;
838 : }
839 :
840 : // ----------------------------------------------------------------------------
841 : // IntergraphDataset::GetGeoTransform()
842 : // ----------------------------------------------------------------------------
843 :
844 21 : CPLErr IntergraphDataset::GetGeoTransform( double *padfTransform )
845 : {
846 21 : if( GDALPamDataset::GetGeoTransform( padfTransform ) != CE_None )
847 : {
848 3 : memcpy( padfTransform, adfGeoTransform, sizeof( double ) * 6 );
849 : }
850 :
851 21 : return CE_None;
852 : }
853 :
854 : // ----------------------------------------------------------------------------
855 : // IntergraphDataset::SetGeoTransform()
856 : // ----------------------------------------------------------------------------
857 :
858 31 : CPLErr IntergraphDataset::SetGeoTransform( double *padfTransform )
859 : {
860 31 : if( GDALPamDataset::SetGeoTransform( padfTransform ) != CE_None )
861 : {
862 0 : memcpy( adfGeoTransform, padfTransform, sizeof( double ) * 6 );
863 : }
864 :
865 31 : INGR_SetTransMatrix( hHeaderOne.TransformationMatrix, padfTransform );
866 :
867 31 : return CE_None;
868 : }
869 :
870 : // ----------------------------------------------------------------------------
871 : // IntergraphDataset::SetProjection()
872 : // ----------------------------------------------------------------------------
873 :
874 31 : CPLErr IntergraphDataset::SetProjection( const char *pszProjString )
875 : {
876 : (void) pszProjString;
877 :
878 31 : return CE_None;
879 : }
880 :
881 : // ----------------------------------------------------------------------------
882 : // GDALRegister_INGR()
883 : // ----------------------------------------------------------------------------
884 :
885 610 : void GDALRegister_INGR()
886 : {
887 : GDALDriver *poDriver;
888 :
889 610 : if( GDALGetDriverByName( "INGR" ) == NULL )
890 : {
891 588 : poDriver = new GDALDriver();
892 :
893 588 : poDriver->SetDescription( "INGR" );
894 588 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Intergraph Raster" );
895 588 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_IntergraphRaster.html" );
896 588 : poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
897 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
898 588 : "Byte Int16 Int32 Float32 Float64" );
899 588 : poDriver->pfnOpen = IntergraphDataset::Open;
900 588 : poDriver->pfnCreate = IntergraphDataset::Create;
901 588 : poDriver->pfnCreateCopy = IntergraphDataset::CreateCopy;
902 588 : GetGDALDriverManager()->RegisterDriver( poDriver );
903 : }
904 610 : }
|