GDALDataset *IntergraphDataset::Open( GDALOpenInfo *poOpenInfo ) { if( poOpenInfo->nHeaderBytes < 1024 ) { return NULL; } // -------------------------------------------------------------------- // Assign Header Information // -------------------------------------------------------------------- INGR_HeaderOne hHeaderOne; INGR_HeaderOneDiskToMem( &hHeaderOne, (GByte*) poOpenInfo->pabyHeader); // -------------------------------------------------------------------- // Check Header Type (HTC) Version // -------------------------------------------------------------------- if( hHeaderOne.HeaderType.Version != INGR_HEADER_VERSION ) { return NULL; } // -------------------------------------------------------------------- // Check Header Type (HTC) 2D / 3D Flag // -------------------------------------------------------------------- if( ( hHeaderOne.HeaderType.Is2Dor3D != INGR_HEADER_2D ) && ( hHeaderOne.HeaderType.Is2Dor3D != INGR_HEADER_3D ) ) { return NULL; } // -------------------------------------------------------------------- // Check Header Type (HTC) Type Flag // -------------------------------------------------------------------- if( hHeaderOne.HeaderType.Type != INGR_HEADER_TYPE ) { return NULL; } // -------------------------------------------------------------------- // Check Grid File Version (VER) // -------------------------------------------------------------------- if( hHeaderOne.GridFileVersion != 1 && hHeaderOne.GridFileVersion != 2 && hHeaderOne.GridFileVersion != 3 ) { return NULL; } // -------------------------------------------------------------------- // Check Words To Follow (WTC) Minimum Value // -------------------------------------------------------------------- if( hHeaderOne.WordsToFollow < 254 ) { return NULL; } // -------------------------------------------------------------------- // Check Words To Follow (WTC) Integrity // -------------------------------------------------------------------- float fHeaderBlocks = (float) ( hHeaderOne.WordsToFollow + 2 ) / 256; if( ( fHeaderBlocks - (int) fHeaderBlocks ) != 0.0 ) { return NULL; } // -------------------------------------------------------------------- // Get Data Type Code (DTC) => Format Type // -------------------------------------------------------------------- INGR_Format eFormat = (INGR_Format) hHeaderOne.DataTypeCode; // -------------------------------------------------------------------- // We need to scan around the file, so we open it now. // -------------------------------------------------------------------- VSILFILE *fp; if( poOpenInfo->eAccess == GA_ReadOnly ) { fp = VSIFOpenL( poOpenInfo->pszFilename, "rb" ); } else { fp = VSIFOpenL( poOpenInfo->pszFilename, "r+b" ); } if( fp == NULL ) { CPLError( CE_Failure, CPLE_OpenFailed, "%s", VSIStrerror( errno ) ); return NULL; } // -------------------------------------------------------------------- // Get Format Type from the tile directory // -------------------------------------------------------------------- if( hHeaderOne.DataTypeCode == TiledRasterData ) { INGR_TileHeader hTileDir; int nOffset = 2 + ( 2 * ( hHeaderOne.WordsToFollow + 1 ) ); GByte abyBuffer[SIZEOF_TDIR]; if( (VSIFSeekL( fp, nOffset, SEEK_SET ) == -1 ) || (VSIFReadL( abyBuffer, 1, SIZEOF_TDIR, fp ) == 0) ) { VSIFCloseL( fp ); CPLError( CE_Failure, CPLE_AppDefined, "Error reading tiles header" ); return NULL; } INGR_TileHeaderDiskToMem( &hTileDir, abyBuffer ); if( ! ( hTileDir.ApplicationType == 1 && hTileDir.SubTypeCode == 7 && ( hTileDir.WordsToFollow % 4 ) == 0 && hTileDir.PacketVersion == 1 && hTileDir.Identifier == 1 ) ) { CPLError( CE_Failure, CPLE_AppDefined, "Cannot recognize tiles header info"); VSIFCloseL( fp ); return NULL; } eFormat = (INGR_Format) hTileDir.DataTypeCode; } // -------------------------------------------------------------------- // Check Scannable Flag // -------------------------------------------------------------------- /* if (hHeaderOne.ScannableFlag == HasLineHeader) { CPLError( CE_Failure, CPLE_AppDefined, "Intergraph Raster Scannable Line Header not supported yet" ); VSIFCloseL( fp ); return NULL; } */ // -------------------------------------------------------------------- // Check supported Format Type // -------------------------------------------------------------------- if( eFormat != ByteInteger && eFormat != WordIntegers && eFormat != Integers32Bit && eFormat != FloatingPoint32Bit && eFormat != FloatingPoint64Bit && eFormat != RunLengthEncoded && eFormat != RunLengthEncodedC && eFormat != CCITTGroup4 && eFormat != AdaptiveRGB && eFormat != Uncompressed24bit && eFormat != AdaptiveGrayScale && eFormat != ContinuousTone && eFormat != JPEGGRAY && eFormat != JPEGRGB && eFormat != JPEGCYMK ) { CPLError( CE_Failure, CPLE_AppDefined, "Intergraph Raster Format %d ( \"%s\" ) not supported", hHeaderOne.DataTypeCode, INGR_GetFormatName( (uint16) eFormat ) ); VSIFCloseL( fp ); return NULL; } // ----------------------------------------------------------------- // Create a corresponding GDALDataset // ----------------------------------------------------------------- IntergraphDataset *poDS; poDS = new IntergraphDataset(); poDS->eAccess = poOpenInfo->eAccess; poDS->pszFilename = CPLStrdup( poOpenInfo->pszFilename ); poDS->fp = fp; // -------------------------------------------------------------------- // Get X Size from Pixels Per Line (PPL) // -------------------------------------------------------------------- poDS->nRasterXSize = hHeaderOne.PixelsPerLine; // -------------------------------------------------------------------- // Get Y Size from Number of Lines (NOL) // -------------------------------------------------------------------- poDS->nRasterYSize = hHeaderOne.NumberOfLines; if (poDS->nRasterXSize <= 0 || poDS->nRasterYSize <= 0) { CPLError( CE_Failure, CPLE_AppDefined, "Invalid dimensions : %d x %d", poDS->nRasterXSize, poDS->nRasterYSize); delete poDS; return NULL; } // -------------------------------------------------------------------- // Get Geo Transformation from Homogeneous Transformation Matrix (TRN) // -------------------------------------------------------------------- INGR_GetTransMatrix( &hHeaderOne, poDS->adfGeoTransform ); // -------------------------------------------------------------------- // Set Metadata Information // -------------------------------------------------------------------- poDS->SetMetadataItem( "VERSION", CPLSPrintf ( "%d", hHeaderOne.GridFileVersion ), "IMAGE_STRUCTURE" ); poDS->SetMetadataItem( "RESOLUTION", CPLSPrintf ( "%d", (hHeaderOne.DeviceResolution < 0)?-hHeaderOne.DeviceResolution:1) ); // -------------------------------------------------------------------- // Create Band Information // -------------------------------------------------------------------- int nBands = 0; int nBandOffset = 0; GByte abyBuf[MAX(SIZEOF_HDR1,SIZEOF_HDR2_A)]; do { VSIFSeekL( poDS->fp, nBandOffset, SEEK_SET ); VSIFReadL( abyBuf, 1, SIZEOF_HDR1, poDS->fp ); INGR_HeaderOneDiskToMem( &poDS->hHeaderOne, abyBuf ); VSIFReadL( abyBuf, 1, SIZEOF_HDR2_A, poDS->fp ); INGR_HeaderTwoADiskToMem( &poDS->hHeaderTwo, abyBuf ); switch( eFormat ) { case JPEGRGB: case JPEGCYMK: { IntergraphBitmapBand* poBand; nBands++; poDS->SetBand( nBands, poBand = new IntergraphBitmapBand( poDS, nBands, nBandOffset, 1 )); if (poBand->pabyBMPBlock == NULL) { delete poDS; return NULL; } nBands++; poDS->SetBand( nBands, poBand = new IntergraphBitmapBand( poDS, nBands, nBandOffset, 2 )); if (poBand->pabyBMPBlock == NULL) { delete poDS; return NULL; } nBands++; poDS->SetBand( nBands, poBand = new IntergraphBitmapBand( poDS, nBands, nBandOffset, 3 )); if (poBand->pabyBMPBlock == NULL) { delete poDS; return NULL; } break; } case JPEGGRAY: case CCITTGroup4: { IntergraphBitmapBand* poBand; nBands++; poDS->SetBand( nBands, poBand = new IntergraphBitmapBand( poDS, nBands, nBandOffset )); if (poBand->pabyBMPBlock == NULL) { delete poDS; return NULL; } break; } case RunLengthEncoded: case RunLengthEncodedC: case AdaptiveGrayScale: { IntergraphRLEBand* poBand; nBands++; poDS->SetBand( nBands, poBand = new IntergraphRLEBand( poDS, nBands, nBandOffset )); if (poBand->pabyBlockBuf == NULL || poBand->pabyRLEBlock == NULL) { delete poDS; return NULL; } break; } case AdaptiveRGB: case ContinuousTone: { IntergraphRLEBand* poBand; nBands++; poDS->SetBand( nBands, poBand = new IntergraphRLEBand( poDS, nBands, nBandOffset, 1 )); if (poBand->pabyBlockBuf == NULL || poBand->pabyRLEBlock == NULL) { delete poDS; return NULL; } nBands++; poDS->SetBand( nBands, poBand = new IntergraphRLEBand( poDS, nBands, nBandOffset, 2 )); if (poBand->pabyBlockBuf == NULL || poBand->pabyRLEBlock == NULL) { delete poDS; return NULL; } nBands++; poDS->SetBand( nBands, poBand = new IntergraphRLEBand( poDS, nBands, nBandOffset, 3 )); if (poBand->pabyBlockBuf == NULL || poBand->pabyRLEBlock == NULL) { delete poDS; return NULL; } break; } case Uncompressed24bit: { IntergraphRGBBand* poBand; nBands++; poDS->SetBand( nBands, poBand = new IntergraphRGBBand( poDS, nBands, nBandOffset, 1 )); if (poBand->pabyBlockBuf == NULL) { delete poDS; return NULL; } nBands++; poDS->SetBand( nBands, poBand = new IntergraphRGBBand( poDS, nBands, nBandOffset, 2 )); if (poBand->pabyBlockBuf == NULL) { delete poDS; return NULL; } nBands++; poDS->SetBand( nBands, poBand = new IntergraphRGBBand( poDS, nBands, nBandOffset, 3 )); if (poBand->pabyBlockBuf == NULL) { delete poDS; return NULL; } break; } default: { IntergraphRasterBand* poBand; nBands++; poDS->SetBand( nBands, poBand = new IntergraphRasterBand( poDS, nBands, nBandOffset )); if (poBand->pabyBlockBuf == NULL) { delete poDS; return NULL; } } } // ---------------------------------------------------------------- // Get next band offset from Catenated File Pointer (CFP) // ---------------------------------------------------------------- nBandOffset = poDS->hHeaderTwo.CatenatedFilePointer; } while( nBandOffset != 0 ); poDS->nBands = nBands; // -------------------------------------------------------------------- // Initialize any PAM information // -------------------------------------------------------------------- poDS->SetDescription( poOpenInfo->pszFilename ); poDS->TryLoadXML(); /* -------------------------------------------------------------------- */ /* Check for external overviews. */ /* -------------------------------------------------------------------- */ poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename ); return ( poDS ); }
IntergraphRasterBand::IntergraphRasterBand( IntergraphDataset *poDS, int nBand, int nBandOffset, GDALDataType eType ) { this->poColorTable = new GDALColorTable(); this->poDS = poDS; this->nBand = nBand != 0 ? nBand : poDS->nBands; this->nTiles = 0; this->eDataType = eType; this->pabyBlockBuf = NULL; this->pahTiles = NULL; this->nRGBIndex = 0; this->nBandStart = nBandOffset; this->bTiled = FALSE; // -------------------------------------------------------------------- // Get Header Info // -------------------------------------------------------------------- memcpy(&hHeaderOne, &poDS->hHeaderOne, sizeof(hHeaderOne)); memcpy(&hHeaderTwo, &poDS->hHeaderTwo, sizeof(hHeaderTwo)); // -------------------------------------------------------------------- // Get the image start from Words to Follow (WTF) // -------------------------------------------------------------------- nDataOffset = nBandOffset + 2 + ( 2 * ( hHeaderOne.WordsToFollow + 1 ) ); // -------------------------------------------------------------------- // Get Color Tabel from Color Table Type (CTV) // -------------------------------------------------------------------- uint32 nEntries = hHeaderTwo.NumberOfCTEntries; if( nEntries > 0 ) { switch ( hHeaderTwo.ColorTableType ) { case EnvironVColorTable: INGR_GetEnvironVColors( poDS->fp, nBandOffset, nEntries, poColorTable ); if (poColorTable->GetColorEntryCount() == 0) return; break; case IGDSColorTable: INGR_GetIGDSColors( poDS->fp, nBandOffset, nEntries, poColorTable ); if (poColorTable->GetColorEntryCount() == 0) return; break; default: CPLDebug( "INGR", "Wrong Color table type (%d), number of colors (%d)", hHeaderTwo.ColorTableType, nEntries ); } } // -------------------------------------------------------------------- // Set Dimension // -------------------------------------------------------------------- nRasterXSize = hHeaderOne.PixelsPerLine; nRasterYSize = hHeaderOne.NumberOfLines; nBlockXSize = nRasterXSize; nBlockYSize = 1; // -------------------------------------------------------------------- // Get tile directory // -------------------------------------------------------------------- this->eFormat = (INGR_Format) hHeaderOne.DataTypeCode; this->bTiled = (hHeaderOne.DataTypeCode == TiledRasterData); if( bTiled ) { nTiles = INGR_GetTileDirectory( poDS->fp, nDataOffset, nRasterXSize, nRasterYSize, &hTileDir, &pahTiles ); if (nTiles == 0) return; eFormat = (INGR_Format) hTileDir.DataTypeCode; // ---------------------------------------------------------------- // Set blocks dimensions based on tiles // ---------------------------------------------------------------- nBlockXSize = MIN( hTileDir.TileSize, (uint32) nRasterXSize ); nBlockYSize = MIN( hTileDir.TileSize, (uint32) nRasterYSize ); } if (nBlockXSize <= 0 || nBlockYSize <= 0) { pabyBlockBuf = NULL; CPLError(CE_Failure, CPLE_AppDefined, "Invalid block dimensions"); return; } // -------------------------------------------------------------------- // Incomplete tiles have Block Offset greater than: // -------------------------------------------------------------------- nFullBlocksX = ( nRasterXSize / nBlockXSize ); nFullBlocksY = ( nRasterYSize / nBlockYSize ); // -------------------------------------------------------------------- // Get the Data Type from Format // -------------------------------------------------------------------- this->eDataType = INGR_GetDataType( (uint16) eFormat ); // -------------------------------------------------------------------- // Allocate buffer for a Block of data // -------------------------------------------------------------------- nBlockBufSize = nBlockXSize * nBlockYSize * GDALGetDataTypeSize( eDataType ) / 8; pabyBlockBuf = (GByte*) VSIMalloc3( nBlockXSize, nBlockYSize, GDALGetDataTypeSize( eDataType ) / 8); if (pabyBlockBuf == NULL) { CPLError(CE_Failure, CPLE_AppDefined, "Cannot allocate %d bytes", nBlockBufSize); return; } // -------------------------------------------------------------------- // More Metadata Information // -------------------------------------------------------------------- SetMetadataItem( "FORMAT", INGR_GetFormatName( (uint16) eFormat ), "IMAGE_STRUCTURE" ); if( bTiled ) { SetMetadataItem( "TILESSIZE", CPLSPrintf ("%d", hTileDir.TileSize), "IMAGE_STRUCTURE" ); } else { SetMetadataItem( "TILED", "NO", "IMAGE_STRUCTURE" ); } SetMetadataItem( "ORIENTATION", INGR_GetOrientation( hHeaderOne.ScanlineOrientation ), "IMAGE_STRUCTURE" ); }
GDALDataset *IntergraphDataset::Create( const char *pszFilename, int nXSize, int nYSize, int nBands, GDALDataType eType, char **papszOptions ) { int nDeviceResolution = 1; const char *pszValue; const char *pszCompression = NULL; pszValue = CSLFetchNameValue(papszOptions, "RESOLUTION"); if( pszValue != NULL ) nDeviceResolution = -atoi( pszValue ); char *pszExtension = CPLStrlwr(CPLStrdup(CPLGetExtension(pszFilename))); if ( EQUAL( pszExtension, "rle" ) ) pszCompression = INGR_GetFormatName(RunLengthEncoded); CPLFree(pszExtension); if( eType != GDT_Byte && eType != GDT_Int16 && eType != GDT_Int32 && eType != GDT_UInt16 && eType != GDT_UInt32 && eType != GDT_Float32&& eType != GDT_Float64 ) { CPLError( CE_Failure, CPLE_AppDefined, "Data type not supported (%s)", GDALGetDataTypeName( eType ) ); return NULL; } // -------------------------------------------------------------------- // Fill headers with minimun information // -------------------------------------------------------------------- INGR_HeaderOne hHdr1; INGR_HeaderTwoA hHdr2; INGR_ColorTable256 hCTab; int i; memset(&hHdr1, 0, SIZEOF_HDR1); memset(&hHdr2, 0, SIZEOF_HDR2_A); memset(&hCTab, 0, SIZEOF_CTAB); hHdr1.HeaderType.Version = INGR_HEADER_VERSION; hHdr1.HeaderType.Type = INGR_HEADER_TYPE; hHdr1.HeaderType.Is2Dor3D = INGR_HEADER_2D; hHdr1.DataTypeCode = (uint16) INGR_GetFormat( eType, (pszCompression!=NULL)?pszCompression:"None" ); hHdr1.WordsToFollow = ( ( SIZEOF_HDR1 * 3 ) / 2 ) - 2; hHdr1.ApplicationType = GenericRasterImageFile; hHdr1.XViewOrigin = 0.0; hHdr1.YViewOrigin = 0.0; hHdr1.ZViewOrigin = 0.0; hHdr1.XViewExtent = 0.0; hHdr1.YViewExtent = 0.0; hHdr1.ZViewExtent = 0.0; for( i = 0; i < 15; i++ ) hHdr1.TransformationMatrix[i] = 0.0; hHdr1.TransformationMatrix[15] = 1.0; hHdr1.PixelsPerLine = nXSize; hHdr1.NumberOfLines = nYSize; hHdr1.DeviceResolution = nDeviceResolution; hHdr1.ScanlineOrientation = UpperLeftHorizontal; hHdr1.ScannableFlag = NoLineHeader; hHdr1.RotationAngle = 0.0; hHdr1.SkewAngle = 0.0; hHdr1.DataTypeModifier = 0; hHdr1.DesignFileName[0] = '\0'; hHdr1.DataBaseFileName[0] = '\0'; hHdr1.ParentGridFileName[0] = '\0'; hHdr1.FileDescription[0] = '\0'; hHdr1.Minimum = INGR_SetMinMax( eType, 0.0 ); hHdr1.Maximum = INGR_SetMinMax( eType, 0.0 ); hHdr1.GridFileVersion = 3; hHdr1.Reserved[0] = 0; hHdr1.Reserved[1] = 0; hHdr1.Reserved[2] = 0; hHdr2.Gain = 0; hHdr2.OffsetThreshold = 0; hHdr2.View1 = 0; hHdr2.View2 = 0; hHdr2.ViewNumber = 0; hHdr2.Reserved2 = 0; hHdr2.Reserved3 = 0; hHdr2.AspectRatio = nXSize / nYSize; hHdr2.CatenatedFilePointer = 0; hHdr2.ColorTableType = NoColorTable; hHdr2.NumberOfCTEntries = 0; hHdr2.Reserved8 = 0; for( i = 0; i < 110; i++ ) hHdr2.Reserved[i] = 0; hHdr2.ApplicationPacketLength = 0; hHdr2.ApplicationPacketPointer = 0; // -------------------------------------------------------------------- // RGB Composite assumption // -------------------------------------------------------------------- if( eType == GDT_Byte && nBands == 3 ) { hHdr1.DataTypeCode = Uncompressed24bit; } // -------------------------------------------------------------------- // Create output file with minimum header info // -------------------------------------------------------------------- VSILFILE *fp = VSIFOpenL( pszFilename, "wb+" ); if( fp == NULL ) { CPLError( CE_Failure, CPLE_OpenFailed, "Attempt to create file %s' failed.\n", pszFilename ); return NULL; } GByte abyBuf[MAX(SIZEOF_HDR1,SIZEOF_CTAB)]; INGR_HeaderOneMemToDisk( &hHdr1, abyBuf ); VSIFWriteL( abyBuf, 1, SIZEOF_HDR1, fp ); INGR_HeaderTwoAMemToDisk( &hHdr2, abyBuf ); VSIFWriteL( abyBuf, 1, SIZEOF_HDR2_A, fp ); unsigned int n = 0; for( i = 0; i < 256; i++ ) { STRC2BUF( abyBuf, n, hCTab.Entry[i].v_red ); STRC2BUF( abyBuf, n, hCTab.Entry[i].v_green ); STRC2BUF( abyBuf, n, hCTab.Entry[i].v_blue ); } VSIFWriteL( abyBuf, 1, SIZEOF_CTAB, fp ); VSIFCloseL( fp ); // -------------------------------------------------------------------- // Returns a new IntergraphDataset from the created file // -------------------------------------------------------------------- return ( IntergraphDataset * ) GDALOpen( pszFilename, GA_Update ); }