1 : /*****************************************************************************
2 : * $Id: IntergraphDataset.cpp 20996 2010-10-28 18:38:15Z 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 73 : IntergraphDataset::IntergraphDataset()
47 : {
48 73 : pszFilename = NULL;
49 73 : fp = NULL;
50 :
51 73 : adfGeoTransform[0] = 0.0;
52 73 : adfGeoTransform[1] = 1.0;
53 73 : adfGeoTransform[2] = 0.0;
54 73 : adfGeoTransform[3] = 0.0;
55 73 : adfGeoTransform[4] = 0.0;
56 73 : adfGeoTransform[5] = 1.0;
57 :
58 73 : hVirtual.poDS = NULL;
59 73 : hVirtual.poBand = NULL;
60 73 : hVirtual.pszFileName = NULL;
61 :
62 73 : memset(&hHeaderOne, 0, sizeof(hHeaderOne));
63 73 : memset(&hHeaderTwo, 0, sizeof(hHeaderTwo));
64 73 : }
65 :
66 : // ----------------------------------------------------------------------------
67 : // IntergraphDataset::~IntergraphDataset()
68 : // ----------------------------------------------------------------------------
69 :
70 73 : IntergraphDataset::~IntergraphDataset()
71 : {
72 73 : FlushCache();
73 :
74 73 : CPLFree( pszFilename );
75 :
76 73 : if( fp != NULL )
77 : {
78 73 : VSIFCloseL( fp );
79 : }
80 73 : }
81 :
82 : // ----------------------------------------------------------------------------
83 : // IntergraphDataset::Open()
84 : // ----------------------------------------------------------------------------
85 :
86 12563 : GDALDataset *IntergraphDataset::Open( GDALOpenInfo *poOpenInfo )
87 : {
88 12563 : if( poOpenInfo->nHeaderBytes < 1024 )
89 : {
90 11836 : return NULL;
91 : }
92 :
93 : // --------------------------------------------------------------------
94 : // Assign Header Information
95 : // --------------------------------------------------------------------
96 :
97 : INGR_HeaderOne hHeaderOne;
98 :
99 727 : INGR_HeaderOneDiskToMem( &hHeaderOne, (GByte*) poOpenInfo->pabyHeader);
100 :
101 : // --------------------------------------------------------------------
102 : // Check Header Type (HTC) Version
103 : // --------------------------------------------------------------------
104 :
105 727 : if( hHeaderOne.HeaderType.Version != INGR_HEADER_VERSION )
106 : {
107 628 : return NULL;
108 : }
109 :
110 : // --------------------------------------------------------------------
111 : // Check Header Type (HTC) 2D / 3D Flag
112 : // --------------------------------------------------------------------
113 :
114 99 : 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 73 : if( hHeaderOne.HeaderType.Type != INGR_HEADER_TYPE )
125 : {
126 0 : return NULL;
127 : }
128 :
129 : // --------------------------------------------------------------------
130 : // Check Grid File Version (VER)
131 : // --------------------------------------------------------------------
132 :
133 73 : 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 73 : if( hHeaderOne.WordsToFollow < 254 )
145 : {
146 0 : return NULL;
147 : }
148 :
149 : // --------------------------------------------------------------------
150 : // Check Words To Follow (WTC) Integrity
151 : // --------------------------------------------------------------------
152 :
153 73 : float fHeaderBlocks = (float) ( hHeaderOne.WordsToFollow + 2 ) / 256;
154 :
155 73 : 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 73 : 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 73 : if( poOpenInfo->eAccess == GA_ReadOnly )
173 : {
174 41 : fp = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
175 : }
176 : else
177 : {
178 32 : fp = VSIFOpenL( poOpenInfo->pszFilename, "r+b" );
179 : }
180 :
181 73 : 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 73 : 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 73 : 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 73 : poDS = new IntergraphDataset();
272 73 : poDS->eAccess = poOpenInfo->eAccess;
273 73 : poDS->pszFilename = CPLStrdup( poOpenInfo->pszFilename );
274 73 : poDS->fp = fp;
275 :
276 : // --------------------------------------------------------------------
277 : // Get X Size from Pixels Per Line (PPL)
278 : // --------------------------------------------------------------------
279 :
280 73 : poDS->nRasterXSize = hHeaderOne.PixelsPerLine;
281 :
282 : // --------------------------------------------------------------------
283 : // Get Y Size from Number of Lines (NOL)
284 : // --------------------------------------------------------------------
285 :
286 73 : poDS->nRasterYSize = hHeaderOne.NumberOfLines;
287 :
288 146 : 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 73 : INGR_GetTransMatrix( &hHeaderOne, poDS->adfGeoTransform );
302 :
303 : // --------------------------------------------------------------------
304 : // Set Metadata Information
305 : // --------------------------------------------------------------------
306 :
307 : poDS->SetMetadataItem( "VERSION",
308 73 : CPLSPrintf ( "%d", hHeaderOne.GridFileVersion ), "IMAGE_STRUCTURE" );
309 :
310 : // --------------------------------------------------------------------
311 : // Create Band Information
312 : // --------------------------------------------------------------------
313 :
314 73 : int nBands = 0;
315 73 : int nBandOffset = 0;
316 :
317 : GByte abyBuf[MAX(SIZEOF_HDR1,SIZEOF_HDR2_A)];
318 :
319 73 : do
320 : {
321 73 : VSIFSeekL( poDS->fp, nBandOffset, SEEK_SET );
322 :
323 73 : VSIFReadL( abyBuf, 1, SIZEOF_HDR1, poDS->fp );
324 :
325 73 : INGR_HeaderOneDiskToMem( &poDS->hHeaderOne, abyBuf );
326 :
327 73 : VSIFReadL( abyBuf, 1, SIZEOF_HDR2_A, poDS->fp );
328 :
329 73 : INGR_HeaderTwoADiskToMem( &poDS->hHeaderTwo, abyBuf );
330 :
331 73 : switch( eFormat )
332 : {
333 : case JPEGRGB:
334 : case JPEGCYMK:
335 : {
336 : IntergraphBitmapBand* poBand;
337 1 : nBands++;
338 : poDS->SetBand( nBands,
339 1 : poBand = new IntergraphBitmapBand( poDS, nBands, nBandOffset, 1 ));
340 1 : if (poBand->pabyBMPBlock == NULL)
341 : {
342 0 : delete poDS;
343 0 : return NULL;
344 : }
345 1 : nBands++;
346 : poDS->SetBand( nBands,
347 1 : poBand = new IntergraphBitmapBand( poDS, nBands, nBandOffset, 2 ));
348 1 : if (poBand->pabyBMPBlock == NULL)
349 : {
350 0 : delete poDS;
351 0 : return NULL;
352 : }
353 1 : nBands++;
354 : poDS->SetBand( nBands,
355 1 : poBand = new IntergraphBitmapBand( poDS, nBands, nBandOffset, 3 ));
356 1 : if (poBand->pabyBMPBlock == NULL)
357 : {
358 0 : delete poDS;
359 0 : return NULL;
360 : }
361 1 : break;
362 : }
363 : case JPEGGRAY:
364 : case CCITTGroup4:
365 : {
366 : IntergraphBitmapBand* poBand;
367 2 : nBands++;
368 : poDS->SetBand( nBands,
369 2 : poBand = new IntergraphBitmapBand( poDS, nBands, nBandOffset ));
370 2 : if (poBand->pabyBMPBlock == NULL)
371 : {
372 0 : delete poDS;
373 0 : return NULL;
374 : }
375 2 : break;
376 : }
377 : case RunLengthEncoded:
378 : case RunLengthEncodedC:
379 : case AdaptiveGrayScale:
380 : {
381 : IntergraphRLEBand* poBand;
382 4 : nBands++;
383 : poDS->SetBand( nBands,
384 4 : poBand = new IntergraphRLEBand( poDS, nBands, nBandOffset ));
385 8 : if (poBand->pabyBlockBuf == NULL || poBand->pabyRLEBlock == NULL)
386 : {
387 0 : delete poDS;
388 0 : return NULL;
389 : }
390 4 : break;
391 : }
392 : case AdaptiveRGB:
393 : case ContinuousTone:
394 : {
395 : IntergraphRLEBand* poBand;
396 1 : nBands++;
397 : poDS->SetBand( nBands,
398 1 : poBand = new IntergraphRLEBand( poDS, nBands, nBandOffset, 1 ));
399 2 : if (poBand->pabyBlockBuf == NULL || poBand->pabyRLEBlock == NULL)
400 : {
401 0 : delete poDS;
402 0 : return NULL;
403 : }
404 1 : nBands++;
405 : poDS->SetBand( nBands,
406 1 : poBand = new IntergraphRLEBand( poDS, nBands, nBandOffset, 2 ));
407 2 : if (poBand->pabyBlockBuf == NULL || poBand->pabyRLEBlock == NULL)
408 : {
409 0 : delete poDS;
410 0 : return NULL;
411 : }
412 1 : nBands++;
413 : poDS->SetBand( nBands,
414 1 : poBand = new IntergraphRLEBand( poDS, nBands, nBandOffset, 3 ));
415 2 : if (poBand->pabyBlockBuf == NULL || poBand->pabyRLEBlock == NULL)
416 : {
417 0 : delete poDS;
418 0 : return NULL;
419 : }
420 1 : break;
421 : }
422 : case Uncompressed24bit:
423 : {
424 : IntergraphRGBBand* poBand;
425 5 : nBands++;
426 : poDS->SetBand( nBands,
427 5 : poBand = new IntergraphRGBBand( poDS, nBands, nBandOffset, 1 ));
428 5 : if (poBand->pabyBlockBuf == NULL)
429 : {
430 0 : delete poDS;
431 0 : return NULL;
432 : }
433 5 : nBands++;
434 : poDS->SetBand( nBands,
435 5 : poBand = new IntergraphRGBBand( poDS, nBands, nBandOffset, 2 ));
436 5 : if (poBand->pabyBlockBuf == NULL)
437 : {
438 0 : delete poDS;
439 0 : return NULL;
440 : }
441 5 : nBands++;
442 : poDS->SetBand( nBands,
443 5 : poBand = new IntergraphRGBBand( poDS, nBands, nBandOffset, 3 ));
444 5 : if (poBand->pabyBlockBuf == NULL)
445 : {
446 0 : delete poDS;
447 0 : return NULL;
448 : }
449 5 : break;
450 : }
451 : default:
452 : {
453 : IntergraphRasterBand* poBand;
454 60 : nBands++;
455 : poDS->SetBand( nBands,
456 60 : poBand = new IntergraphRasterBand( poDS, nBands, nBandOffset ));
457 60 : if (poBand->pabyBlockBuf == NULL)
458 : {
459 0 : delete poDS;
460 0 : return NULL;
461 : }
462 : }
463 : }
464 :
465 : // ----------------------------------------------------------------
466 : // Get next band offset from Catenated File Pointer (CFP)
467 : // ----------------------------------------------------------------
468 :
469 73 : nBandOffset = poDS->hHeaderTwo.CatenatedFilePointer;
470 : }
471 : while( nBandOffset != 0 );
472 :
473 73 : poDS->nBands = nBands;
474 :
475 : // --------------------------------------------------------------------
476 : // Initialize any PAM information
477 : // --------------------------------------------------------------------
478 :
479 73 : poDS->SetDescription( poOpenInfo->pszFilename );
480 73 : poDS->TryLoadXML();
481 :
482 : /* -------------------------------------------------------------------- */
483 : /* Check for external overviews. */
484 : /* -------------------------------------------------------------------- */
485 :
486 73 : poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
487 :
488 73 : return ( poDS );
489 : }
490 :
491 : // ----------------------------------------------------------------------------
492 : // IntergraphDataset::Create()
493 : // ----------------------------------------------------------------------------
494 :
495 46 : GDALDataset *IntergraphDataset::Create( const char *pszFilename,
496 : int nXSize,
497 : int nYSize,
498 : int nBands,
499 : GDALDataType eType,
500 : char **papszOptions )
501 : {
502 : (void) papszOptions;
503 :
504 46 : if( eType != GDT_Byte &&
505 : eType != GDT_Int16 &&
506 : eType != GDT_Int32 &&
507 : eType != GDT_UInt16 &&
508 : eType != GDT_UInt32 &&
509 : eType != GDT_Float32&&
510 : eType != GDT_Float64 )
511 : {
512 : CPLError( CE_Failure, CPLE_AppDefined, "Data type not supported (%s)",
513 12 : GDALGetDataTypeName( eType ) );
514 12 : return NULL;
515 : }
516 :
517 : // --------------------------------------------------------------------
518 : // Fill headers with minimun information
519 : // --------------------------------------------------------------------
520 :
521 : INGR_HeaderOne hHdr1;
522 : INGR_HeaderTwoA hHdr2;
523 : INGR_ColorTable256 hCTab;
524 : int i;
525 :
526 34 : memset(&hHdr1, 0, SIZEOF_HDR1);
527 34 : memset(&hHdr2, 0, SIZEOF_HDR2_A);
528 34 : memset(&hCTab, 0, SIZEOF_CTAB);
529 :
530 34 : hHdr1.HeaderType.Version = INGR_HEADER_VERSION;
531 34 : hHdr1.HeaderType.Type = INGR_HEADER_TYPE;
532 34 : hHdr1.HeaderType.Is2Dor3D = INGR_HEADER_2D;
533 34 : hHdr1.DataTypeCode = (uint16) INGR_GetFormat( eType, "None" );
534 34 : hHdr1.WordsToFollow = ( ( SIZEOF_HDR1 * 3 ) / 2 ) - 2;
535 34 : hHdr1.ApplicationType = GenericRasterImageFile;
536 34 : hHdr1.XViewOrigin = 0.0;
537 34 : hHdr1.YViewOrigin = 0.0;
538 34 : hHdr1.ZViewOrigin = 0.0;
539 34 : hHdr1.XViewExtent = 0.0;
540 34 : hHdr1.YViewExtent = 0.0;
541 34 : hHdr1.ZViewExtent = 0.0;
542 544 : for( i = 0; i < 15; i++ )
543 510 : hHdr1.TransformationMatrix[i] = 0.0;
544 34 : hHdr1.TransformationMatrix[15] = 1.0;
545 34 : hHdr1.PixelsPerLine = nXSize;
546 34 : hHdr1.NumberOfLines = nYSize;
547 34 : hHdr1.DeviceResolution = 1;
548 34 : hHdr1.ScanlineOrientation = UpperLeftHorizontal;
549 34 : hHdr1.ScannableFlag = NoLineHeader;
550 34 : hHdr1.RotationAngle = 0.0;
551 34 : hHdr1.SkewAngle = 0.0;
552 34 : hHdr1.DataTypeModifier = 0;
553 34 : hHdr1.DesignFileName[0] = '\0';
554 34 : hHdr1.DataBaseFileName[0] = '\0';
555 34 : hHdr1.ParentGridFileName[0] = '\0';
556 34 : hHdr1.FileDescription[0] = '\0';
557 34 : hHdr1.Minimum = INGR_SetMinMax( eType, 0.0 );
558 34 : hHdr1.Maximum = INGR_SetMinMax( eType, 0.0 );
559 34 : hHdr1.GridFileVersion = 3;
560 34 : hHdr1.Reserved[0] = 0;
561 34 : hHdr1.Reserved[1] = 0;
562 34 : hHdr1.Reserved[2] = 0;
563 34 : hHdr2.Gain = 0;
564 34 : hHdr2.OffsetThreshold = 0;
565 34 : hHdr2.View1 = 0;
566 34 : hHdr2.View2 = 0;
567 34 : hHdr2.ViewNumber = 0;
568 34 : hHdr2.Reserved2 = 0;
569 34 : hHdr2.Reserved3 = 0;
570 34 : hHdr2.AspectRatio = nXSize / nYSize;
571 34 : hHdr2.CatenatedFilePointer = 0;
572 34 : hHdr2.ColorTableType = NoColorTable;
573 34 : hHdr2.NumberOfCTEntries = 0;
574 34 : hHdr2.Reserved8 = 0;
575 3774 : for( i = 0; i < 110; i++ )
576 3740 : hHdr2.Reserved[i] = 0;
577 34 : hHdr2.ApplicationPacketLength = 0;
578 34 : hHdr2.ApplicationPacketPointer = 0;
579 :
580 : // --------------------------------------------------------------------
581 : // RGB Composite assumption
582 : // --------------------------------------------------------------------
583 :
584 34 : if( eType == GDT_Byte &&
585 : nBands == 3 )
586 : {
587 2 : hHdr1.DataTypeCode = Uncompressed24bit;
588 : }
589 :
590 : // --------------------------------------------------------------------
591 : // Create output file with minimum header info
592 : // --------------------------------------------------------------------
593 :
594 34 : VSILFILE *fp = VSIFOpenL( pszFilename, "wb+" );
595 :
596 34 : if( fp == NULL )
597 : {
598 : CPLError( CE_Failure, CPLE_OpenFailed,
599 2 : "Attempt to create file %s' failed.\n", pszFilename );
600 2 : return NULL;
601 : }
602 :
603 : GByte abyBuf[MAX(SIZEOF_HDR1,SIZEOF_CTAB)];
604 :
605 32 : INGR_HeaderOneMemToDisk( &hHdr1, abyBuf );
606 :
607 32 : VSIFWriteL( abyBuf, 1, SIZEOF_HDR1, fp );
608 :
609 32 : INGR_HeaderTwoAMemToDisk( &hHdr2, abyBuf );
610 :
611 32 : VSIFWriteL( abyBuf, 1, SIZEOF_HDR2_A, fp );
612 :
613 32 : unsigned int n = 0;
614 :
615 8224 : for( i = 0; i < 256; i++ )
616 : {
617 8192 : STRC2BUF( abyBuf, n, hCTab.Entry[i].v_red );
618 8192 : STRC2BUF( abyBuf, n, hCTab.Entry[i].v_green );
619 8192 : STRC2BUF( abyBuf, n, hCTab.Entry[i].v_blue );
620 : }
621 :
622 32 : VSIFWriteL( abyBuf, 1, SIZEOF_CTAB, fp );
623 :
624 32 : VSIFCloseL( fp );
625 :
626 : // --------------------------------------------------------------------
627 : // Returns a new IntergraphDataset from the created file
628 : // --------------------------------------------------------------------
629 :
630 32 : return ( IntergraphDataset * ) GDALOpen( pszFilename, GA_Update );
631 : }
632 :
633 : // ----------------------------------------------------------------------------
634 : // IntergraphDataset::CreateCopy()
635 : // ----------------------------------------------------------------------------
636 :
637 19 : GDALDataset *IntergraphDataset::CreateCopy( const char *pszFilename,
638 : GDALDataset *poSrcDS,
639 : int bStrict,
640 : char **papszOptions,
641 : GDALProgressFunc pfnProgress,
642 : void *pProgressData )
643 : {
644 : (void) bStrict;
645 :
646 19 : int nBands = poSrcDS->GetRasterCount();
647 19 : if (nBands == 0)
648 : {
649 : CPLError( CE_Failure, CPLE_NotSupported,
650 1 : "Intergraph driver does not support source dataset with zero band.\n");
651 1 : return NULL;
652 : }
653 :
654 18 : if( !pfnProgress( 0.0, NULL, pProgressData ) )
655 : {
656 0 : return NULL;
657 : }
658 :
659 : // --------------------------------------------------------------------
660 : // Query GDAL Data Type
661 : // --------------------------------------------------------------------
662 :
663 18 : GDALDataType eType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
664 :
665 : // --------------------------------------------------------------------
666 : // Create IntergraphDataset
667 : // --------------------------------------------------------------------
668 :
669 : IntergraphDataset *poDstDS;
670 :
671 : poDstDS = (IntergraphDataset*) IntergraphDataset::Create( pszFilename,
672 : poSrcDS->GetRasterXSize(),
673 : poSrcDS->GetRasterYSize(),
674 : poSrcDS->GetRasterCount(),
675 : eType,
676 18 : papszOptions );
677 :
678 18 : if( poDstDS == NULL )
679 : {
680 6 : return NULL;
681 : }
682 :
683 : // --------------------------------------------------------------------
684 : // Copy Transformation Matrix to the dataset
685 : // --------------------------------------------------------------------
686 :
687 : double adfGeoTransform[6];
688 :
689 12 : poDstDS->SetProjection( poSrcDS->GetProjectionRef() );
690 12 : poSrcDS->GetGeoTransform( adfGeoTransform );
691 12 : poDstDS->SetGeoTransform( adfGeoTransform );
692 :
693 : // --------------------------------------------------------------------
694 : // Copy information to the raster band
695 : // --------------------------------------------------------------------
696 :
697 : GDALRasterBand *poSrcBand;
698 : GDALRasterBand *poDstBand;
699 : double dfMin;
700 : double dfMax;
701 : double dfMean;
702 12 : double dfStdDev = -1;
703 :
704 26 : for( int i = 1; i <= poDstDS->nBands; i++)
705 : {
706 14 : delete poDstDS->GetRasterBand(i);
707 : }
708 12 : poDstDS->nBands = 0;
709 :
710 12 : if( poDstDS->hHeaderOne.DataTypeCode == Uncompressed24bit )
711 : {
712 1 : poDstDS->SetBand( 1, new IntergraphRGBBand( poDstDS, 1, 0, 3 ) );
713 2 : poDstDS->SetBand( 2, new IntergraphRGBBand( poDstDS, 2, 0, 2 ) );
714 2 : poDstDS->SetBand( 3, new IntergraphRGBBand( poDstDS, 3, 0, 1 ) );
715 1 : poDstDS->nBands = 3;
716 : }
717 : else
718 : {
719 60 : for( int i = 1; i <= poSrcDS->GetRasterCount(); i++ )
720 : {
721 19 : poSrcBand = poSrcDS->GetRasterBand(i);
722 19 : eType = poSrcDS->GetRasterBand(i)->GetRasterDataType();
723 :
724 19 : poDstBand = new IntergraphRasterBand( poDstDS, i, 0, eType );
725 19 : poDstDS->SetBand( i, poDstBand );
726 :
727 19 : poDstBand->SetCategoryNames( poSrcBand->GetCategoryNames() );
728 19 : poDstBand->SetColorTable( poSrcBand->GetColorTable() );
729 19 : poSrcBand->GetStatistics( false, true, &dfMin, &dfMax, &dfMean, &dfStdDev );
730 19 : poDstBand->SetStatistics( dfMin, dfMax, dfMean, dfStdDev );
731 : }
732 : }
733 :
734 : // --------------------------------------------------------------------
735 : // Copy image data
736 : // --------------------------------------------------------------------
737 :
738 12 : int nXSize = poDstDS->GetRasterXSize();
739 12 : int nYSize = poDstDS->GetRasterYSize();
740 :
741 : int nBlockXSize;
742 : int nBlockYSize;
743 :
744 12 : CPLErr eErr = CE_None;
745 :
746 34 : for( int iBand = 1; iBand <= poSrcDS->GetRasterCount(); iBand++ )
747 : {
748 22 : GDALRasterBand *poDstBand = poDstDS->GetRasterBand( iBand );
749 22 : GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( iBand );
750 :
751 : // ------------------------------------------------------------
752 : // Copy Untiled / Uncompressed
753 : // ------------------------------------------------------------
754 :
755 : int iYOffset, iXOffset;
756 : void *pData;
757 :
758 22 : poSrcBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
759 :
760 22 : nBlockXSize = nXSize;
761 22 : nBlockYSize = 1;
762 :
763 22 : pData = CPLMalloc( nBlockXSize * nBlockYSize * GDALGetDataTypeSize( eType ) / 8 );
764 :
765 382 : for( iYOffset = 0; iYOffset < nYSize; iYOffset += nBlockYSize )
766 : {
767 720 : for( iXOffset = 0; iXOffset < nXSize; iXOffset += nBlockXSize )
768 : {
769 : eErr = poSrcBand->RasterIO( GF_Read,
770 : iXOffset, iYOffset,
771 : nBlockXSize, nBlockYSize,
772 : pData, nBlockXSize, nBlockYSize,
773 360 : eType, 0, 0 );
774 360 : if( eErr != CE_None )
775 : {
776 0 : return NULL;
777 : }
778 : eErr = poDstBand->RasterIO( GF_Write,
779 : iXOffset, iYOffset,
780 : nBlockXSize, nBlockYSize,
781 : pData, nBlockXSize, nBlockYSize,
782 360 : eType, 0, 0 );
783 360 : if( eErr != CE_None )
784 : {
785 0 : return NULL;
786 : }
787 : }
788 360 : if( ( eErr == CE_None ) && ( ! pfnProgress(
789 : ( iYOffset + 1 ) / ( double ) nYSize, NULL, pProgressData ) ) )
790 : {
791 0 : eErr = CE_Failure;
792 0 : CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated CreateCopy()" );
793 : }
794 : }
795 22 : CPLFree( pData );
796 : }
797 :
798 : // --------------------------------------------------------------------
799 : // Finalize
800 : // --------------------------------------------------------------------
801 :
802 12 : poDstDS->FlushCache();
803 :
804 12 : return poDstDS;
805 : }
806 :
807 : // ----------------------------------------------------------------------------
808 : // IntergraphDataset::GetGeoTransform()
809 : // ----------------------------------------------------------------------------
810 :
811 20 : CPLErr IntergraphDataset::GetGeoTransform( double *padfTransform )
812 : {
813 20 : if( GDALPamDataset::GetGeoTransform( padfTransform ) != CE_None )
814 : {
815 2 : memcpy( padfTransform, adfGeoTransform, sizeof( double ) * 6 );
816 : }
817 :
818 20 : return CE_None;
819 : }
820 :
821 : // ----------------------------------------------------------------------------
822 : // IntergraphDataset::SetGeoTransform()
823 : // ----------------------------------------------------------------------------
824 :
825 30 : CPLErr IntergraphDataset::SetGeoTransform( double *padfTransform )
826 : {
827 30 : if( GDALPamDataset::SetGeoTransform( padfTransform ) != CE_None )
828 : {
829 0 : memcpy( adfGeoTransform, padfTransform, sizeof( double ) * 6 );
830 : }
831 :
832 30 : INGR_SetTransMatrix( hHeaderOne.TransformationMatrix, padfTransform );
833 :
834 30 : return CE_None;
835 : }
836 :
837 : // ----------------------------------------------------------------------------
838 : // IntergraphDataset::SetProjection()
839 : // ----------------------------------------------------------------------------
840 :
841 30 : CPLErr IntergraphDataset::SetProjection( const char *pszProjString )
842 : {
843 : (void) pszProjString;
844 :
845 30 : return CE_None;
846 : }
847 :
848 : // ----------------------------------------------------------------------------
849 : // GDALRegister_INGR()
850 : // ----------------------------------------------------------------------------
851 :
852 582 : void GDALRegister_INGR()
853 : {
854 : GDALDriver *poDriver;
855 :
856 582 : if( GDALGetDriverByName( "INGR" ) == NULL )
857 : {
858 561 : poDriver = new GDALDriver();
859 :
860 561 : poDriver->SetDescription( "INGR" );
861 561 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Intergraph Raster" );
862 561 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_IntergraphRaster.html" );
863 561 : poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
864 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
865 561 : "Byte Int16 Int32 Float32 Float64" );
866 561 : poDriver->pfnOpen = IntergraphDataset::Open;
867 561 : poDriver->pfnCreate = IntergraphDataset::Create;
868 561 : poDriver->pfnCreateCopy = IntergraphDataset::CreateCopy;
869 561 : GetGDALDriverManager()->RegisterDriver( poDriver );
870 : }
871 582 : }
|