mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-06-19 14:15:21 -06:00
2151 lines
75 KiB
C++
2151 lines
75 KiB
C++
/******************************************************************************
|
|
* $Id: pcidskdataset2.cpp 28292 2015-01-05 19:35:55Z rouault $
|
|
*
|
|
* Project: PCIDSK Database File
|
|
* Purpose: Read/write PCIDSK Database File used by the PCI software, using
|
|
* the external PCIDSK library.
|
|
* Author: Frank Warmerdam, warmerdam@pobox.com
|
|
*
|
|
******************************************************************************
|
|
* Copyright (c) 2009, Frank Warmerdam <warmerdam@pobox.com>
|
|
* Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included
|
|
* in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
****************************************************************************/
|
|
|
|
#include "pcidskdataset2.h"
|
|
|
|
CPL_CVSID("$Id: pcidskdataset2.cpp 28292 2015-01-05 19:35:55Z rouault $");
|
|
|
|
const PCIDSK::PCIDSKInterfaces *PCIDSK2GetInterfaces(void);
|
|
|
|
/************************************************************************/
|
|
/* ==================================================================== */
|
|
/* PCIDSK2Band */
|
|
/* ==================================================================== */
|
|
/************************************************************************/
|
|
|
|
/************************************************************************/
|
|
/* PCIDSK2Band() */
|
|
/* */
|
|
/* This constructor is used for main file channels. */
|
|
/************************************************************************/
|
|
|
|
PCIDSK2Band::PCIDSK2Band( PCIDSK2Dataset *poDS,
|
|
PCIDSKFile *poFile,
|
|
int nBand )
|
|
|
|
{
|
|
Initialize();
|
|
|
|
this->poDS = poDS;
|
|
this->poFile = poFile;
|
|
this->nBand = nBand;
|
|
|
|
poChannel = poFile->GetChannel( nBand );
|
|
|
|
nBlockXSize = (int) poChannel->GetBlockWidth();
|
|
nBlockYSize = (int) poChannel->GetBlockHeight();
|
|
|
|
eDataType = PCIDSK2Dataset::PCIDSKTypeToGDAL( poChannel->GetType() );
|
|
|
|
if( !EQUALN(poChannel->GetDescription().c_str(),
|
|
"Contents Not Specified",20) )
|
|
GDALMajorObject::SetDescription( poChannel->GetDescription().c_str() );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Do we have overviews? */
|
|
/* -------------------------------------------------------------------- */
|
|
RefreshOverviewList();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* PCIDSK2Band() */
|
|
/* */
|
|
/* This constructor is used for overviews and bitmap segments */
|
|
/* as bands. */
|
|
/************************************************************************/
|
|
|
|
PCIDSK2Band::PCIDSK2Band( PCIDSKChannel *poChannel )
|
|
|
|
{
|
|
Initialize();
|
|
|
|
this->poChannel = poChannel;
|
|
|
|
nBand = 1;
|
|
|
|
nBlockXSize = (int) poChannel->GetBlockWidth();
|
|
nBlockYSize = (int) poChannel->GetBlockHeight();
|
|
|
|
nRasterXSize = (int) poChannel->GetWidth();
|
|
nRasterYSize = (int) poChannel->GetHeight();
|
|
|
|
eDataType = PCIDSK2Dataset::PCIDSKTypeToGDAL( poChannel->GetType() );
|
|
|
|
if( poChannel->GetType() == CHN_BIT )
|
|
{
|
|
SetMetadataItem( "NBITS", "1", "IMAGE_STRUCTURE" );
|
|
|
|
if( !EQUALN(poChannel->GetDescription().c_str(),
|
|
"Contents Not Specified",20) )
|
|
GDALMajorObject::SetDescription( poChannel->GetDescription().c_str() );
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Initialize() */
|
|
/************************************************************************/
|
|
|
|
void PCIDSK2Band::Initialize()
|
|
|
|
{
|
|
papszLastMDListValue = NULL;
|
|
|
|
poChannel = NULL;
|
|
poFile = NULL;
|
|
poDS = NULL;
|
|
|
|
bCheckedForColorTable = false;
|
|
poColorTable = NULL;
|
|
nPCTSegNumber = -1;
|
|
|
|
papszCategoryNames = NULL;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* ~PCIDSK2Band() */
|
|
/************************************************************************/
|
|
|
|
PCIDSK2Band::~PCIDSK2Band()
|
|
|
|
{
|
|
while( apoOverviews.size() > 0 )
|
|
{
|
|
delete apoOverviews[apoOverviews.size()-1];
|
|
apoOverviews.pop_back();
|
|
}
|
|
CSLDestroy( papszLastMDListValue );
|
|
CSLDestroy( papszCategoryNames );
|
|
|
|
delete poColorTable;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* SetDescription() */
|
|
/************************************************************************/
|
|
|
|
void PCIDSK2Band::SetDescription( const char *pszDescription )
|
|
|
|
{
|
|
try
|
|
{
|
|
poChannel->SetDescription( pszDescription );
|
|
|
|
if( !EQUALN(poChannel->GetDescription().c_str(),
|
|
"Contents Not Specified",20) )
|
|
GDALMajorObject::SetDescription( poChannel->GetDescription().c_str() );
|
|
}
|
|
catch( PCIDSKException ex )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"%s", ex.what() );
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetCategoryNames() */
|
|
/* */
|
|
/* Offer category names from Class_*_ metadata. */
|
|
/************************************************************************/
|
|
|
|
char **PCIDSK2Band::GetCategoryNames()
|
|
|
|
{
|
|
// already scanned?
|
|
if( papszCategoryNames != NULL )
|
|
return papszCategoryNames;
|
|
|
|
try
|
|
{
|
|
std::vector<std::string> aosMDKeys = poChannel->GetMetadataKeys();
|
|
size_t i;
|
|
int nClassCount = 0;
|
|
static const int nMaxClasses = 10000;
|
|
papszCategoryNames = (char **) CPLCalloc(nMaxClasses+1, sizeof(char*));
|
|
|
|
for( i=0; i < aosMDKeys.size(); i++ )
|
|
{
|
|
CPLString osKey = aosMDKeys[i];
|
|
|
|
// is this a "Class_n_name" keyword?
|
|
|
|
if( !EQUALN(osKey,"Class_",6) )
|
|
continue;
|
|
|
|
if( !EQUAL(osKey.c_str() + osKey.size() - 5, "_name") )
|
|
continue;
|
|
|
|
// Ignore unreasonable class values.
|
|
int iClass = atoi(osKey.c_str() + 6);
|
|
|
|
if( iClass < 0 || iClass > 10000 )
|
|
continue;
|
|
|
|
// Fetch the name.
|
|
CPLString osName = poChannel->GetMetadataValue(osKey);
|
|
|
|
// do we need to put in place dummy class names for missing values?
|
|
if( iClass >= nClassCount )
|
|
{
|
|
while( iClass >= nClassCount )
|
|
{
|
|
papszCategoryNames[nClassCount++] = CPLStrdup("");
|
|
papszCategoryNames[nClassCount] = NULL;
|
|
}
|
|
}
|
|
|
|
// Replace target category name.
|
|
CPLFree( papszCategoryNames[iClass] );
|
|
papszCategoryNames[iClass] = NULL;
|
|
|
|
papszCategoryNames[iClass] = CPLStrdup(osName);
|
|
}
|
|
|
|
if( nClassCount == 0 )
|
|
return GDALPamRasterBand::GetCategoryNames();
|
|
else
|
|
return papszCategoryNames;
|
|
}
|
|
catch( PCIDSKException ex )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"%s", ex.what() );
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* CheckForColorTable() */
|
|
/************************************************************************/
|
|
|
|
bool PCIDSK2Band::CheckForColorTable()
|
|
|
|
{
|
|
if( bCheckedForColorTable || poFile == NULL )
|
|
return true;
|
|
|
|
bCheckedForColorTable = true;
|
|
|
|
try
|
|
{
|
|
/* -------------------------------------------------------------------- */
|
|
/* Try to find an appropriate PCT segment to use. */
|
|
/* -------------------------------------------------------------------- */
|
|
std::string osDefaultPCT = poChannel->GetMetadataValue("DEFAULT_PCT_REF");
|
|
PCIDSKSegment *poPCTSeg = NULL;
|
|
|
|
// If there is no metadata, assume a single PCT in a file with only
|
|
// one raster band must be intended for it.
|
|
if( osDefaultPCT.size() == 0
|
|
&& poDS != NULL
|
|
&& poDS->GetRasterCount() == 1 )
|
|
{
|
|
poPCTSeg = poFile->GetSegment( SEG_PCT, "" );
|
|
if( poPCTSeg != NULL
|
|
&& poFile->GetSegment( SEG_PCT, "",
|
|
poPCTSeg->GetSegmentNumber() ) != NULL )
|
|
poPCTSeg = NULL;
|
|
}
|
|
// Parse default PCT ref assuming an in file reference.
|
|
else if( osDefaultPCT.size() != 0
|
|
&& strstr(osDefaultPCT.c_str(),"PCT:") != NULL )
|
|
{
|
|
poPCTSeg = poFile->GetSegment(
|
|
atoi(strstr(osDefaultPCT.c_str(),"PCT:") + 4) );
|
|
}
|
|
|
|
if( poPCTSeg != NULL )
|
|
{
|
|
PCIDSK_PCT *poPCT = dynamic_cast<PCIDSK_PCT*>( poPCTSeg );
|
|
poColorTable = new GDALColorTable();
|
|
int i;
|
|
unsigned char abyPCT[768];
|
|
|
|
nPCTSegNumber = poPCTSeg->GetSegmentNumber();
|
|
|
|
poPCT->ReadPCT( abyPCT );
|
|
|
|
for( i = 0; i < 256; i++ )
|
|
{
|
|
GDALColorEntry sEntry;
|
|
|
|
sEntry.c1 = abyPCT[256 * 0 + i];
|
|
sEntry.c2 = abyPCT[256 * 1 + i];
|
|
sEntry.c3 = abyPCT[256 * 2 + i];
|
|
sEntry.c4 = 255;
|
|
poColorTable->SetColorEntry( i, &sEntry );
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* If we did not find an appropriate PCT segment, check for */
|
|
/* Class_n color data from which to construct a color table. */
|
|
/* -------------------------------------------------------------------- */
|
|
std::vector<std::string> aosMDKeys = poChannel->GetMetadataKeys();
|
|
size_t i;
|
|
|
|
for( i=0; i < aosMDKeys.size(); i++ )
|
|
{
|
|
CPLString osKey = aosMDKeys[i];
|
|
|
|
// is this a "Class_n_name" keyword?
|
|
|
|
if( !EQUALN(osKey,"Class_",6) )
|
|
continue;
|
|
|
|
if( !EQUAL(osKey.c_str() + osKey.size() - 6, "_Color") )
|
|
continue;
|
|
|
|
// Ignore unreasonable class values.
|
|
int iClass = atoi(osKey.c_str() + 6);
|
|
|
|
if( iClass < 0 || iClass > 10000 )
|
|
continue;
|
|
|
|
// Fetch and parse the RGB value "(RGB:red green blue)"
|
|
CPLString osRGB = poChannel->GetMetadataValue(osKey);
|
|
int nRed, nGreen, nBlue;
|
|
|
|
if( !EQUALN(osRGB,"(RGB:",5) )
|
|
continue;
|
|
|
|
if( sscanf( osRGB.c_str() + 5, "%d %d %d",
|
|
&nRed, &nGreen, &nBlue ) != 3 )
|
|
continue;
|
|
|
|
// we have an entry - apply to the color table.
|
|
GDALColorEntry sEntry;
|
|
|
|
sEntry.c1 = (short) nRed;
|
|
sEntry.c2 = (short) nGreen;
|
|
sEntry.c3 = (short) nBlue;
|
|
sEntry.c4 = 255;
|
|
|
|
if( poColorTable == NULL )
|
|
{
|
|
CPLDebug( "PCIDSK", "Using Class_n_Color metadata for color table." );
|
|
poColorTable = new GDALColorTable();
|
|
}
|
|
|
|
poColorTable->SetColorEntry( iClass, &sEntry );
|
|
}
|
|
}
|
|
catch( PCIDSKException ex )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"%s", ex.what() );
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetColorTable() */
|
|
/************************************************************************/
|
|
|
|
GDALColorTable *PCIDSK2Band::GetColorTable()
|
|
|
|
{
|
|
CheckForColorTable();
|
|
|
|
if( poColorTable )
|
|
return poColorTable;
|
|
else
|
|
return GDALPamRasterBand::GetColorTable();
|
|
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* SetColorTable() */
|
|
/************************************************************************/
|
|
|
|
CPLErr PCIDSK2Band::SetColorTable( GDALColorTable *poCT )
|
|
|
|
{
|
|
if( !CheckForColorTable() )
|
|
return CE_Failure;
|
|
|
|
// no color tables on overviews.
|
|
if( poFile == NULL )
|
|
return CE_Failure;
|
|
|
|
try
|
|
{
|
|
/* -------------------------------------------------------------------- */
|
|
/* Are we trying to delete the color table? */
|
|
/* -------------------------------------------------------------------- */
|
|
if( poCT == NULL )
|
|
{
|
|
delete poColorTable;
|
|
poColorTable = NULL;
|
|
|
|
if( nPCTSegNumber != -1 )
|
|
poFile->DeleteSegment( nPCTSegNumber );
|
|
poChannel->SetMetadataValue( "DEFAULT_PCT_REF", "" );
|
|
nPCTSegNumber = -1;
|
|
|
|
return CE_None;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Do we need to create the segment? If so, also set the */
|
|
/* default pct metadata. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( nPCTSegNumber == -1 )
|
|
{
|
|
nPCTSegNumber = poFile->CreateSegment( "PCTTable",
|
|
"Default Pseudo-Color Table",
|
|
SEG_PCT, 0 );
|
|
|
|
CPLString osRef;
|
|
|
|
osRef.Printf( "gdb:/{PCT:%d}", nPCTSegNumber );
|
|
poChannel->SetMetadataValue( "DEFAULT_PCT_REF", osRef );
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Write out the PCT. */
|
|
/* -------------------------------------------------------------------- */
|
|
unsigned char abyPCT[768];
|
|
int i, nColorCount = MIN(256,poCT->GetColorEntryCount());
|
|
|
|
memset( abyPCT, 0, 768 );
|
|
|
|
for( i = 0; i < nColorCount; i++ )
|
|
{
|
|
GDALColorEntry sEntry;
|
|
|
|
poCT->GetColorEntryAsRGB( i, &sEntry );
|
|
abyPCT[256 * 0 + i] = (unsigned char) sEntry.c1;
|
|
abyPCT[256 * 1 + i] = (unsigned char) sEntry.c2;
|
|
abyPCT[256 * 2 + i] = (unsigned char) sEntry.c3;
|
|
}
|
|
|
|
PCIDSK_PCT *poPCT = dynamic_cast<PCIDSK_PCT*>(
|
|
poFile->GetSegment( nPCTSegNumber ) );
|
|
|
|
poPCT->WritePCT( abyPCT );
|
|
|
|
delete poColorTable;
|
|
poColorTable = poCT->Clone();
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Trap exceptions. */
|
|
/* -------------------------------------------------------------------- */
|
|
catch( PCIDSKException ex )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"%s", ex.what() );
|
|
return CE_Failure;
|
|
}
|
|
|
|
return CE_None;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetColorInterpretation() */
|
|
/************************************************************************/
|
|
|
|
GDALColorInterp PCIDSK2Band::GetColorInterpretation()
|
|
|
|
{
|
|
CheckForColorTable();
|
|
|
|
if( poColorTable != NULL )
|
|
return GCI_PaletteIndex;
|
|
else
|
|
return GDALPamRasterBand::GetColorInterpretation();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* RefreshOverviewList() */
|
|
/************************************************************************/
|
|
|
|
void PCIDSK2Band::RefreshOverviewList()
|
|
|
|
{
|
|
/* -------------------------------------------------------------------- */
|
|
/* Clear existing overviews. */
|
|
/* -------------------------------------------------------------------- */
|
|
while( apoOverviews.size() > 0 )
|
|
{
|
|
delete apoOverviews[apoOverviews.size()-1];
|
|
apoOverviews.pop_back();
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Fetch overviews. */
|
|
/* -------------------------------------------------------------------- */
|
|
for( int iOver = 0; iOver < poChannel->GetOverviewCount(); iOver++ )
|
|
{
|
|
apoOverviews.push_back(
|
|
new PCIDSK2Band( poChannel->GetOverview(iOver) ) );
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* IReadBlock() */
|
|
/************************************************************************/
|
|
|
|
CPLErr PCIDSK2Band::IReadBlock( int iBlockX, int iBlockY, void *pData )
|
|
|
|
{
|
|
try
|
|
{
|
|
poChannel->ReadBlock( iBlockX + iBlockY * nBlocksPerRow,
|
|
pData );
|
|
|
|
// Do we need to upsample 1bit to 8bit?
|
|
if( poChannel->GetType() == CHN_BIT )
|
|
{
|
|
GByte *pabyData = (GByte *) pData;
|
|
|
|
for( int ii = nBlockXSize * nBlockYSize - 1; ii >= 0; ii-- )
|
|
{
|
|
if( (pabyData[ii>>3] & (0x80 >> (ii & 0x7))) )
|
|
pabyData[ii] = 1;
|
|
else
|
|
pabyData[ii] = 0;
|
|
}
|
|
}
|
|
|
|
return CE_None;
|
|
}
|
|
catch( PCIDSKException ex )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"%s", ex.what() );
|
|
return CE_Failure;
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* IWriteBlock() */
|
|
/************************************************************************/
|
|
|
|
CPLErr PCIDSK2Band::IWriteBlock( int iBlockX, int iBlockY, void *pData )
|
|
|
|
{
|
|
try
|
|
{
|
|
poChannel->WriteBlock( iBlockX + iBlockY * nBlocksPerRow,
|
|
pData );
|
|
return CE_None;
|
|
}
|
|
catch( PCIDSKException ex )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"%s", ex.what() );
|
|
return CE_Failure;
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetOverviewCount() */
|
|
/************************************************************************/
|
|
|
|
int PCIDSK2Band::GetOverviewCount()
|
|
|
|
{
|
|
if( apoOverviews.size() > 0 )
|
|
return (int) apoOverviews.size();
|
|
else
|
|
return GDALPamRasterBand::GetOverviewCount();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetOverview() */
|
|
/************************************************************************/
|
|
|
|
GDALRasterBand *PCIDSK2Band::GetOverview(int iOverview)
|
|
|
|
{
|
|
if( iOverview < 0 || iOverview >= (int) apoOverviews.size() )
|
|
return GDALPamRasterBand::GetOverview( iOverview );
|
|
else
|
|
return apoOverviews[iOverview];
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* SetMetadata() */
|
|
/************************************************************************/
|
|
|
|
CPLErr PCIDSK2Band::SetMetadata( char **papszMD,
|
|
const char *pszDomain )
|
|
|
|
{
|
|
/* -------------------------------------------------------------------- */
|
|
/* PCIDSK only supports metadata in the default domain. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( pszDomain != NULL && strlen(pszDomain) > 0 )
|
|
return GDALPamRasterBand::SetMetadata( papszMD, pszDomain );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Set each item individually. */
|
|
/* -------------------------------------------------------------------- */
|
|
CSLDestroy( papszLastMDListValue );
|
|
papszLastMDListValue = NULL;
|
|
|
|
try
|
|
{
|
|
int iItem;
|
|
|
|
for( iItem = 0; papszMD && papszMD[iItem]; iItem++ )
|
|
{
|
|
const char *pszItemValue;
|
|
char *pszItemName = NULL;
|
|
|
|
pszItemValue = CPLParseNameValue( papszMD[iItem], &pszItemName);
|
|
if( pszItemName != NULL )
|
|
{
|
|
poChannel->SetMetadataValue( pszItemName, pszItemValue );
|
|
CPLFree( pszItemName );
|
|
}
|
|
}
|
|
return CE_None;
|
|
}
|
|
catch( PCIDSKException ex )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"%s", ex.what() );
|
|
return CE_Failure;
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* SetMetadataItem() */
|
|
/************************************************************************/
|
|
|
|
CPLErr PCIDSK2Band::SetMetadataItem( const char *pszName,
|
|
const char *pszValue,
|
|
const char *pszDomain )
|
|
|
|
{
|
|
/* -------------------------------------------------------------------- */
|
|
/* PCIDSK only supports metadata in the default domain. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( pszDomain != NULL && strlen(pszDomain) > 0 )
|
|
return GDALPamRasterBand::SetMetadataItem(pszName,pszValue,pszDomain);
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Set on the file. */
|
|
/* -------------------------------------------------------------------- */
|
|
CSLDestroy( papszLastMDListValue );
|
|
papszLastMDListValue = NULL;
|
|
|
|
try
|
|
{
|
|
if( !pszValue )
|
|
pszValue = "";
|
|
poChannel->SetMetadataValue( pszName, pszValue );
|
|
return CE_None;
|
|
}
|
|
catch( PCIDSKException ex )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"%s", ex.what() );
|
|
return CE_Failure;
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetMetadataDomainList() */
|
|
/************************************************************************/
|
|
|
|
char **PCIDSK2Band::GetMetadataDomainList()
|
|
{
|
|
return BuildMetadataDomainList(GDALPamRasterBand::GetMetadataDomainList(),
|
|
TRUE,
|
|
"", NULL);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetMetadataItem() */
|
|
/************************************************************************/
|
|
|
|
const char *PCIDSK2Band::GetMetadataItem( const char *pszName,
|
|
const char *pszDomain )
|
|
|
|
{
|
|
/* -------------------------------------------------------------------- */
|
|
/* PCIDSK only supports metadata in the default domain. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( pszDomain != NULL && strlen(pszDomain) > 0 )
|
|
return GDALPamRasterBand::GetMetadataItem( pszName, pszDomain );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Try and fetch. */
|
|
/* -------------------------------------------------------------------- */
|
|
try
|
|
{
|
|
osLastMDValue = poChannel->GetMetadataValue( pszName );
|
|
|
|
if( osLastMDValue == "" )
|
|
return NULL;
|
|
else
|
|
return osLastMDValue.c_str();
|
|
}
|
|
catch( PCIDSKException ex )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"%s", ex.what() );
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetMetadata() */
|
|
/************************************************************************/
|
|
|
|
char **PCIDSK2Band::GetMetadata( const char *pszDomain )
|
|
|
|
{
|
|
/* -------------------------------------------------------------------- */
|
|
/* PCIDSK only supports metadata in the default domain. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( pszDomain != NULL && strlen(pszDomain) > 0 )
|
|
return GDALPamRasterBand::GetMetadata( pszDomain );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* If we have a cached result, just use that. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( papszLastMDListValue != NULL )
|
|
return papszLastMDListValue;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Fetch and build the list. */
|
|
/* -------------------------------------------------------------------- */
|
|
try
|
|
{
|
|
std::vector<std::string> aosKeys = poChannel->GetMetadataKeys();
|
|
unsigned int i;
|
|
|
|
for( i = 0; i < aosKeys.size(); i++ )
|
|
{
|
|
if( aosKeys[i].c_str()[0] == '_' )
|
|
continue;
|
|
|
|
papszLastMDListValue =
|
|
CSLSetNameValue( papszLastMDListValue,
|
|
aosKeys[i].c_str(),
|
|
poChannel->GetMetadataValue(aosKeys[i]).c_str() );
|
|
}
|
|
}
|
|
catch( PCIDSKException ex )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"%s", ex.what() );
|
|
return NULL;
|
|
}
|
|
|
|
return papszLastMDListValue;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* ==================================================================== */
|
|
/* PCIDSK2Dataset */
|
|
/* ==================================================================== */
|
|
/************************************************************************/
|
|
|
|
/************************************************************************/
|
|
/* PCIDSK2Dataset() */
|
|
/************************************************************************/
|
|
|
|
PCIDSK2Dataset::PCIDSK2Dataset()
|
|
{
|
|
poFile = NULL;
|
|
papszLastMDListValue = NULL;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* ~PCIDSK2Dataset() */
|
|
/************************************************************************/
|
|
|
|
PCIDSK2Dataset::~PCIDSK2Dataset()
|
|
{
|
|
FlushCache();
|
|
|
|
while( apoLayers.size() > 0 )
|
|
{
|
|
delete apoLayers.back();
|
|
apoLayers.pop_back();
|
|
}
|
|
|
|
try {
|
|
delete poFile;
|
|
poFile = NULL;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Trap exceptions. */
|
|
/* -------------------------------------------------------------------- */
|
|
catch( PCIDSKException ex )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"%s", ex.what() );
|
|
}
|
|
catch( ... )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"PCIDSK SDK Failure in Close(), unexpected exception." );
|
|
}
|
|
|
|
CSLDestroy( papszLastMDListValue );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetFileList() */
|
|
/************************************************************************/
|
|
|
|
char **PCIDSK2Dataset::GetFileList()
|
|
|
|
{
|
|
char **papszFileList = GDALPamDataset::GetFileList();
|
|
CPLString osBaseDir = CPLGetPath( GetDescription() );
|
|
|
|
try
|
|
{
|
|
for( int nChan = 1; nChan <= poFile->GetChannels(); nChan++ )
|
|
{
|
|
PCIDSKChannel *poChannel = poFile->GetChannel( nChan );
|
|
CPLString osChanFilename;
|
|
uint64 image_offset, pixel_offset, line_offset;
|
|
bool little_endian;
|
|
|
|
poChannel->GetChanInfo( osChanFilename, image_offset,
|
|
pixel_offset, line_offset, little_endian );
|
|
|
|
if( osChanFilename != "" )
|
|
{
|
|
papszFileList =
|
|
CSLAddString( papszFileList,
|
|
CPLProjectRelativeFilename( osBaseDir,
|
|
osChanFilename ) );
|
|
}
|
|
}
|
|
|
|
return papszFileList;
|
|
}
|
|
catch( PCIDSKException ex )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"%s", ex.what() );
|
|
return papszFileList;
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* ProcessRPC() */
|
|
/************************************************************************/
|
|
|
|
void PCIDSK2Dataset::ProcessRPC()
|
|
|
|
{
|
|
/* -------------------------------------------------------------------- */
|
|
/* Search all BIN segments looking for an RPC segment. */
|
|
/* -------------------------------------------------------------------- */
|
|
PCIDSKSegment *poSeg = poFile->GetSegment( SEG_BIN, "" );
|
|
PCIDSKRPCSegment *poRPCSeg = NULL;
|
|
|
|
while( poSeg != NULL
|
|
&& (poRPCSeg = dynamic_cast<PCIDSKRPCSegment*>( poSeg )) == NULL )
|
|
|
|
{
|
|
poSeg = poFile->GetSegment( SEG_BIN, "",
|
|
poSeg->GetSegmentNumber() );
|
|
}
|
|
|
|
if( poRPCSeg == NULL )
|
|
return;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Turn RPC segment into GDAL RFC 22 style metadata. */
|
|
/* -------------------------------------------------------------------- */
|
|
try
|
|
{
|
|
CPLString osValue;
|
|
double dfLineOffset, dfLineScale, dfSampOffset, dfSampScale;
|
|
double dfLatOffset, dfLatScale,
|
|
dfLongOffset, dfLongScale,
|
|
dfHeightOffset, dfHeightScale;
|
|
|
|
poRPCSeg->GetRPCTranslationCoeffs(
|
|
dfLongOffset, dfLongScale,
|
|
dfLatOffset, dfLatScale,
|
|
dfHeightOffset, dfHeightScale,
|
|
dfSampOffset, dfSampScale,
|
|
dfLineOffset, dfLineScale );
|
|
|
|
osValue.Printf( "%.16g", dfLineOffset );
|
|
GDALPamDataset::SetMetadataItem( "LINE_OFF", osValue, "RPC" );
|
|
|
|
osValue.Printf( "%.16g", dfLineScale );
|
|
GDALPamDataset::SetMetadataItem( "LINE_SCALE", osValue, "RPC" );
|
|
|
|
osValue.Printf( "%.16g", dfSampOffset );
|
|
GDALPamDataset::SetMetadataItem( "SAMP_OFF", osValue, "RPC" );
|
|
|
|
osValue.Printf( "%.16g", dfSampScale );
|
|
GDALPamDataset::SetMetadataItem( "SAMP_SCALE", osValue, "RPC" );
|
|
|
|
osValue.Printf( "%.16g", dfLongOffset );
|
|
GDALPamDataset::SetMetadataItem( "LONG_OFF", osValue, "RPC" );
|
|
|
|
osValue.Printf( "%.16g", dfLongScale );
|
|
GDALPamDataset::SetMetadataItem( "LONG_SCALE", osValue, "RPC" );
|
|
|
|
osValue.Printf( "%.16g", dfLatOffset );
|
|
GDALPamDataset::SetMetadataItem( "LAT_OFF", osValue, "RPC" );
|
|
|
|
osValue.Printf( "%.16g", dfLatScale );
|
|
GDALPamDataset::SetMetadataItem( "LAT_SCALE", osValue, "RPC" );
|
|
|
|
osValue.Printf( "%.16g", dfHeightOffset );
|
|
GDALPamDataset::SetMetadataItem( "HEIGHT_OFF", osValue, "RPC" );
|
|
|
|
osValue.Printf( "%.16g", dfHeightScale );
|
|
GDALPamDataset::SetMetadataItem( "HEIGHT_SCALE", osValue, "RPC" );
|
|
|
|
CPLString osCoefList;
|
|
std::vector<double> adfCoef;
|
|
int i;
|
|
|
|
if( poRPCSeg->GetXNumerator().size() != 20
|
|
|| poRPCSeg->GetXDenominator().size() != 20
|
|
|| poRPCSeg->GetYNumerator().size() != 20
|
|
|| poRPCSeg->GetYDenominator().size() != 20 )
|
|
{
|
|
GDALPamDataset::SetMetadata( NULL, "RPC" );
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"Did not get 20 values in the RPC coefficients lists." );
|
|
return;
|
|
}
|
|
|
|
adfCoef = poRPCSeg->GetYNumerator();
|
|
osCoefList = "";
|
|
for( i = 0; i < 20; i++ )
|
|
{
|
|
osValue.Printf( "%.16g ", adfCoef[i] );
|
|
osCoefList += osValue;
|
|
}
|
|
GDALPamDataset::SetMetadataItem( "LINE_NUM_COEFF", osCoefList, "RPC" );
|
|
|
|
adfCoef = poRPCSeg->GetYDenominator();
|
|
osCoefList = "";
|
|
for( i = 0; i < 20; i++ )
|
|
{
|
|
osValue.Printf( "%.16g ", adfCoef[i] );
|
|
osCoefList += osValue;
|
|
}
|
|
GDALPamDataset::SetMetadataItem( "LINE_DEN_COEFF", osCoefList, "RPC" );
|
|
|
|
adfCoef = poRPCSeg->GetXNumerator();
|
|
osCoefList = "";
|
|
for( i = 0; i < 20; i++ )
|
|
{
|
|
osValue.Printf( "%.16g ", adfCoef[i] );
|
|
osCoefList += osValue;
|
|
}
|
|
GDALPamDataset::SetMetadataItem( "SAMP_NUM_COEFF", osCoefList, "RPC" );
|
|
|
|
adfCoef = poRPCSeg->GetXDenominator();
|
|
osCoefList = "";
|
|
for( i = 0; i < 20; i++ )
|
|
{
|
|
osValue.Printf( "%.16g ", adfCoef[i] );
|
|
osCoefList += osValue;
|
|
}
|
|
GDALPamDataset::SetMetadataItem( "SAMP_DEN_COEFF", osCoefList, "RPC" );
|
|
}
|
|
catch( PCIDSKException ex )
|
|
{
|
|
GDALPamDataset::SetMetadata( NULL, "RPC" );
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"%s", ex.what() );
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* FlushCache() */
|
|
/************************************************************************/
|
|
|
|
void PCIDSK2Dataset::FlushCache()
|
|
|
|
{
|
|
GDALPamDataset::FlushCache();
|
|
|
|
if( poFile )
|
|
{
|
|
try {
|
|
poFile->Synchronize();
|
|
}
|
|
catch( PCIDSKException ex )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"%s", ex.what() );
|
|
}
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* SetMetadata() */
|
|
/************************************************************************/
|
|
|
|
CPLErr PCIDSK2Dataset::SetMetadata( char **papszMD,
|
|
const char *pszDomain )
|
|
|
|
{
|
|
/* -------------------------------------------------------------------- */
|
|
/* PCIDSK only supports metadata in the default domain. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( pszDomain != NULL && strlen(pszDomain) > 0 )
|
|
return GDALPamDataset::SetMetadata( papszMD, pszDomain );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Set each item individually. */
|
|
/* -------------------------------------------------------------------- */
|
|
CSLDestroy( papszLastMDListValue );
|
|
papszLastMDListValue = NULL;
|
|
|
|
try
|
|
{
|
|
int iItem;
|
|
|
|
for( iItem = 0; papszMD && papszMD[iItem]; iItem++ )
|
|
{
|
|
const char *pszItemValue;
|
|
char *pszItemName = NULL;
|
|
|
|
pszItemValue = CPLParseNameValue( papszMD[iItem], &pszItemName);
|
|
if( pszItemName != NULL )
|
|
{
|
|
poFile->SetMetadataValue( pszItemName, pszItemValue );
|
|
CPLFree( pszItemName );
|
|
}
|
|
}
|
|
return CE_None;
|
|
}
|
|
catch( PCIDSKException ex )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"%s", ex.what() );
|
|
return CE_Failure;
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* SetMetadataItem() */
|
|
/************************************************************************/
|
|
|
|
CPLErr PCIDSK2Dataset::SetMetadataItem( const char *pszName,
|
|
const char *pszValue,
|
|
const char *pszDomain )
|
|
|
|
{
|
|
/* -------------------------------------------------------------------- */
|
|
/* PCIDSK only supports metadata in the default domain. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( pszDomain != NULL && strlen(pszDomain) > 0 )
|
|
return GDALPamDataset::SetMetadataItem( pszName, pszValue, pszDomain );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Set on the file. */
|
|
/* -------------------------------------------------------------------- */
|
|
CSLDestroy( papszLastMDListValue );
|
|
papszLastMDListValue = NULL;
|
|
|
|
try
|
|
{
|
|
poFile->SetMetadataValue( pszName, pszValue );
|
|
return CE_None;
|
|
}
|
|
catch( PCIDSKException ex )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"%s", ex.what() );
|
|
return CE_Failure;
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetMetadataDomainList() */
|
|
/************************************************************************/
|
|
|
|
char **PCIDSK2Dataset::GetMetadataDomainList()
|
|
{
|
|
return BuildMetadataDomainList(GDALPamDataset::GetMetadataDomainList(),
|
|
TRUE,
|
|
"", NULL);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetMetadataItem() */
|
|
/************************************************************************/
|
|
|
|
const char *PCIDSK2Dataset::GetMetadataItem( const char *pszName,
|
|
const char *pszDomain )
|
|
|
|
{
|
|
/* -------------------------------------------------------------------- */
|
|
/* PCIDSK only supports metadata in the default domain. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( pszDomain != NULL && strlen(pszDomain) > 0 )
|
|
return GDALPamDataset::GetMetadataItem( pszName, pszDomain );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Try and fetch. */
|
|
/* -------------------------------------------------------------------- */
|
|
try
|
|
{
|
|
osLastMDValue = poFile->GetMetadataValue( pszName );
|
|
|
|
if( osLastMDValue == "" )
|
|
return NULL;
|
|
else
|
|
return osLastMDValue.c_str();
|
|
}
|
|
catch( PCIDSKException ex )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"%s", ex.what() );
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetMetadata() */
|
|
/************************************************************************/
|
|
|
|
char **PCIDSK2Dataset::GetMetadata( const char *pszDomain )
|
|
|
|
{
|
|
/* -------------------------------------------------------------------- */
|
|
/* PCIDSK only supports metadata in the default domain. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( pszDomain != NULL && strlen(pszDomain) > 0 )
|
|
return GDALPamDataset::GetMetadata( pszDomain );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* If we have a cached result, just use that. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( papszLastMDListValue != NULL )
|
|
return papszLastMDListValue;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Fetch and build the list. */
|
|
/* -------------------------------------------------------------------- */
|
|
try
|
|
{
|
|
std::vector<std::string> aosKeys = poFile->GetMetadataKeys();
|
|
unsigned int i;
|
|
|
|
for( i = 0; i < aosKeys.size(); i++ )
|
|
{
|
|
if( aosKeys[i].c_str()[0] == '_' )
|
|
continue;
|
|
|
|
papszLastMDListValue =
|
|
CSLSetNameValue( papszLastMDListValue,
|
|
aosKeys[i].c_str(),
|
|
poFile->GetMetadataValue(aosKeys[i]).c_str() );
|
|
}
|
|
}
|
|
catch( PCIDSKException ex )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"%s", ex.what() );
|
|
return NULL;
|
|
}
|
|
|
|
return papszLastMDListValue;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* SetGeoTransform() */
|
|
/************************************************************************/
|
|
|
|
CPLErr PCIDSK2Dataset::SetGeoTransform( double * padfTransform )
|
|
{
|
|
PCIDSKGeoref *poGeoref = NULL;
|
|
try
|
|
{
|
|
PCIDSKSegment *poGeoSeg = poFile->GetSegment(1);
|
|
poGeoref = dynamic_cast<PCIDSKGeoref*>( poGeoSeg );
|
|
}
|
|
catch( PCIDSKException ex )
|
|
{
|
|
// I should really check whether this is an expected issue.
|
|
}
|
|
|
|
if( poGeoref == NULL )
|
|
return GDALPamDataset::SetGeoTransform( padfTransform );
|
|
else
|
|
{
|
|
try
|
|
{
|
|
poGeoref->WriteSimple( poGeoref->GetGeosys(),
|
|
padfTransform[0],
|
|
padfTransform[1],
|
|
padfTransform[2],
|
|
padfTransform[3],
|
|
padfTransform[4],
|
|
padfTransform[5] );
|
|
}
|
|
catch( PCIDSKException ex )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"%s", ex.what() );
|
|
return CE_Failure;
|
|
}
|
|
|
|
return CE_None;
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetGeoTransform() */
|
|
/************************************************************************/
|
|
|
|
CPLErr PCIDSK2Dataset::GetGeoTransform( double * padfTransform )
|
|
{
|
|
PCIDSKGeoref *poGeoref = NULL;
|
|
try
|
|
{
|
|
PCIDSKSegment *poGeoSeg = poFile->GetSegment(1);
|
|
poGeoref = dynamic_cast<PCIDSKGeoref*>( poGeoSeg );
|
|
}
|
|
catch( PCIDSKException ex )
|
|
{
|
|
// I should really check whether this is an expected issue.
|
|
}
|
|
|
|
if( poGeoref != NULL )
|
|
{
|
|
try
|
|
{
|
|
poGeoref->GetTransform( padfTransform[0],
|
|
padfTransform[1],
|
|
padfTransform[2],
|
|
padfTransform[3],
|
|
padfTransform[4],
|
|
padfTransform[5] );
|
|
}
|
|
catch( PCIDSKException ex )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"%s", ex.what() );
|
|
return CE_Failure;
|
|
}
|
|
|
|
// If we got anything non-default return it.
|
|
if( padfTransform[0] != 0.0
|
|
|| padfTransform[1] != 1.0
|
|
|| padfTransform[2] != 0.0
|
|
|| padfTransform[3] != 0.0
|
|
|| padfTransform[4] != 0.0
|
|
|| padfTransform[5] != 1.0 )
|
|
return CE_None;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Check for worldfile if we have no other georeferencing. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( GDALReadWorldFile( GetDescription(), "pxw",
|
|
padfTransform ) )
|
|
return CE_None;
|
|
else
|
|
return GDALPamDataset::GetGeoTransform( padfTransform );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* SetProjection() */
|
|
/************************************************************************/
|
|
|
|
CPLErr PCIDSK2Dataset::SetProjection( const char *pszWKT )
|
|
|
|
{
|
|
osSRS = "";
|
|
|
|
PCIDSKGeoref *poGeoref = NULL;
|
|
|
|
try
|
|
{
|
|
PCIDSKSegment *poGeoSeg = poFile->GetSegment(1);
|
|
poGeoref = dynamic_cast<PCIDSKGeoref*>( poGeoSeg );
|
|
}
|
|
catch( PCIDSKException ex )
|
|
{
|
|
// I should really check whether this is an expected issue.
|
|
}
|
|
|
|
if( poGeoref == NULL )
|
|
{
|
|
return GDALPamDataset::SetProjection( pszWKT );
|
|
}
|
|
else
|
|
{
|
|
char *pszGeosys = NULL;
|
|
char *pszUnits = NULL;
|
|
double *padfPrjParams = NULL;
|
|
|
|
OGRSpatialReference oSRS;
|
|
char *pszWKTWork = (char *) pszWKT;
|
|
|
|
if( oSRS.importFromWkt( &pszWKTWork ) == OGRERR_NONE
|
|
&& oSRS.exportToPCI( &pszGeosys, &pszUnits,
|
|
&padfPrjParams ) == OGRERR_NONE )
|
|
{
|
|
try
|
|
{
|
|
double adfGT[6];
|
|
std::vector<double> adfPCIParameters;
|
|
unsigned int i;
|
|
|
|
poGeoref->GetTransform( adfGT[0], adfGT[1], adfGT[2],
|
|
adfGT[3], adfGT[4], adfGT[5] );
|
|
|
|
poGeoref->WriteSimple( pszGeosys,
|
|
adfGT[0], adfGT[1], adfGT[2],
|
|
adfGT[3], adfGT[4], adfGT[5] );
|
|
|
|
for( i = 0; i < 17; i++ )
|
|
adfPCIParameters.push_back( padfPrjParams[i] );
|
|
|
|
if( EQUALN(pszUnits,"FOOT",4) )
|
|
adfPCIParameters.push_back(
|
|
(double)(int) PCIDSK::UNIT_US_FOOT );
|
|
else if( EQUALN(pszUnits,"INTL FOOT",9) )
|
|
adfPCIParameters.push_back(
|
|
(double)(int) PCIDSK::UNIT_INTL_FOOT );
|
|
else if( EQUALN(pszUnits,"DEGREE",6) )
|
|
adfPCIParameters.push_back(
|
|
(double)(int) PCIDSK::UNIT_DEGREE );
|
|
else
|
|
adfPCIParameters.push_back(
|
|
(double)(int) PCIDSK::UNIT_METER );
|
|
|
|
poGeoref->WriteParameters( adfPCIParameters );
|
|
}
|
|
catch( PCIDSKException ex )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"%s", ex.what() );
|
|
return CE_Failure;
|
|
}
|
|
|
|
CPLFree( pszGeosys );
|
|
CPLFree( pszUnits );
|
|
CPLFree( padfPrjParams );
|
|
|
|
return CE_None;
|
|
}
|
|
else
|
|
return GDALPamDataset::SetProjection( pszWKT );
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetProjectionRef() */
|
|
/************************************************************************/
|
|
|
|
const char *PCIDSK2Dataset::GetProjectionRef()
|
|
{
|
|
if( osSRS != "" )
|
|
return osSRS.c_str();
|
|
|
|
PCIDSKGeoref *poGeoref = NULL;
|
|
|
|
try
|
|
{
|
|
PCIDSKSegment *poGeoSeg = poFile->GetSegment(1);
|
|
poGeoref = dynamic_cast<PCIDSKGeoref*>( poGeoSeg );
|
|
}
|
|
catch( PCIDSKException ex )
|
|
{
|
|
// I should really check whether this is an expected issue.
|
|
}
|
|
|
|
if( poGeoref == NULL )
|
|
{
|
|
osSRS = GDALPamDataset::GetProjectionRef();
|
|
}
|
|
else
|
|
{
|
|
CPLString osGeosys;
|
|
const char *pszUnits = NULL;
|
|
OGRSpatialReference oSRS;
|
|
char *pszWKT = NULL;
|
|
std::vector<double> adfParameters;
|
|
|
|
adfParameters.resize(18);
|
|
try
|
|
{
|
|
if( poGeoref )
|
|
{
|
|
osGeosys = poGeoref->GetGeosys();
|
|
adfParameters = poGeoref->GetParameters();
|
|
if( ((UnitCode)(int)adfParameters[16])
|
|
== PCIDSK::UNIT_DEGREE )
|
|
pszUnits = "DEGREE";
|
|
else if( ((UnitCode)(int)adfParameters[16])
|
|
== PCIDSK::UNIT_METER )
|
|
pszUnits = "METER";
|
|
else if( ((UnitCode)(int)adfParameters[16])
|
|
== PCIDSK::UNIT_US_FOOT )
|
|
pszUnits = "FOOT";
|
|
else if( ((UnitCode)(int)adfParameters[16])
|
|
== PCIDSK::UNIT_INTL_FOOT )
|
|
pszUnits = "INTL FOOT";
|
|
}
|
|
}
|
|
catch( PCIDSKException ex )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"%s", ex.what() );
|
|
}
|
|
|
|
if( oSRS.importFromPCI( osGeosys, pszUnits,
|
|
&(adfParameters[0]) ) == OGRERR_NONE )
|
|
{
|
|
oSRS.exportToWkt( &pszWKT );
|
|
osSRS = pszWKT;
|
|
CPLFree( pszWKT );
|
|
}
|
|
else
|
|
{
|
|
osSRS = GDALPamDataset::GetProjectionRef();
|
|
}
|
|
}
|
|
|
|
return osSRS.c_str();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* IBuildOverviews() */
|
|
/************************************************************************/
|
|
|
|
CPLErr PCIDSK2Dataset::IBuildOverviews( const char *pszResampling,
|
|
int nOverviews, int *panOverviewList,
|
|
int nListBands, int *panBandList,
|
|
GDALProgressFunc pfnProgress,
|
|
void *pProgressData )
|
|
|
|
{
|
|
if( nListBands == 0 )
|
|
return CE_None;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Currently no support for clearing overviews. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( nOverviews == 0 )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"PCIDSK2 driver does not currently support clearing existing overviews. " );
|
|
return CE_Failure;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Establish which of the overview levels we already have, and */
|
|
/* which are new. We assume that band 1 of the file is */
|
|
/* representative. */
|
|
/* -------------------------------------------------------------------- */
|
|
int i, nNewOverviews, *panNewOverviewList = NULL;
|
|
PCIDSK2Band *poBand = (PCIDSK2Band*) GetRasterBand( panBandList[0] );
|
|
|
|
nNewOverviews = 0;
|
|
panNewOverviewList = (int *) CPLCalloc(sizeof(int),nOverviews);
|
|
for( i = 0; i < nOverviews && poBand != NULL; i++ )
|
|
{
|
|
int j;
|
|
|
|
for( j = 0; j < poBand->GetOverviewCount(); j++ )
|
|
{
|
|
int nOvFactor;
|
|
GDALRasterBand * poOverview = poBand->GetOverview( j );
|
|
|
|
nOvFactor = GDALComputeOvFactor(poOverview->GetXSize(),
|
|
poBand->GetXSize(),
|
|
poOverview->GetYSize(),
|
|
poBand->GetYSize());
|
|
|
|
if( nOvFactor == panOverviewList[i]
|
|
|| nOvFactor == GDALOvLevelAdjust2( panOverviewList[i],
|
|
poBand->GetXSize(),
|
|
poBand->GetYSize() ) )
|
|
panOverviewList[i] *= -1;
|
|
}
|
|
|
|
if( panOverviewList[i] > 0 )
|
|
panNewOverviewList[nNewOverviews++] = panOverviewList[i];
|
|
else
|
|
panOverviewList[i] *= -1;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Create the overviews that are missing. */
|
|
/* -------------------------------------------------------------------- */
|
|
for( i = 0; i < nNewOverviews; i++ )
|
|
{
|
|
try
|
|
{
|
|
// conveniently our resampling values mostly match PCIDSK.
|
|
poFile->CreateOverviews( nListBands, panBandList,
|
|
panNewOverviewList[i], pszResampling );
|
|
}
|
|
catch( PCIDSKException ex )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"%s", ex.what() );
|
|
CPLFree( panNewOverviewList );
|
|
return CE_Failure;
|
|
}
|
|
}
|
|
|
|
CPLFree( panNewOverviewList );
|
|
panNewOverviewList = NULL;
|
|
|
|
int iBand;
|
|
for( iBand = 0; iBand < nListBands; iBand++ )
|
|
{
|
|
poBand = (PCIDSK2Band *) GetRasterBand( panBandList[iBand] );
|
|
((PCIDSK2Band *) poBand)->RefreshOverviewList();
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Actually generate the overview imagery. */
|
|
/* -------------------------------------------------------------------- */
|
|
GDALRasterBand **papoOverviewBands;
|
|
CPLErr eErr = CE_None;
|
|
std::vector<int> anRegenLevels;
|
|
|
|
papoOverviewBands = (GDALRasterBand **)
|
|
CPLCalloc(sizeof(void*),nOverviews);
|
|
|
|
for( iBand = 0; iBand < nListBands && eErr == CE_None; iBand++ )
|
|
{
|
|
nNewOverviews = 0;
|
|
|
|
poBand = (PCIDSK2Band*) GetRasterBand( panBandList[iBand] );
|
|
|
|
for( i = 0; i < nOverviews && poBand != NULL; i++ )
|
|
{
|
|
int j;
|
|
|
|
for( j = 0; j < poBand->GetOverviewCount(); j++ )
|
|
{
|
|
int nOvFactor;
|
|
GDALRasterBand * poOverview = poBand->GetOverview( j );
|
|
|
|
nOvFactor = GDALComputeOvFactor(poOverview->GetXSize(),
|
|
poBand->GetXSize(),
|
|
poOverview->GetYSize(),
|
|
poBand->GetYSize());
|
|
|
|
if( nOvFactor == panOverviewList[i]
|
|
|| nOvFactor == GDALOvLevelAdjust2( panOverviewList[i],
|
|
poBand->GetXSize(),
|
|
poBand->GetYSize() ) )
|
|
{
|
|
papoOverviewBands[nNewOverviews++] = poOverview;
|
|
anRegenLevels.push_back( j );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( nNewOverviews > 0 )
|
|
{
|
|
eErr = GDALRegenerateOverviews( (GDALRasterBandH) poBand,
|
|
nNewOverviews,
|
|
(GDALRasterBandH*)papoOverviewBands,
|
|
pszResampling,
|
|
pfnProgress, pProgressData );
|
|
|
|
// Mark the regenerated overviews as valid.
|
|
for( i = 0; i < (int) anRegenLevels.size(); i++ )
|
|
poBand->poChannel->SetOverviewValidity( anRegenLevels[i],
|
|
true );
|
|
}
|
|
}
|
|
|
|
CPLFree(papoOverviewBands);
|
|
|
|
return eErr;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* PCIDSKTypeToGDAL() */
|
|
/************************************************************************/
|
|
|
|
GDALDataType PCIDSK2Dataset::PCIDSKTypeToGDAL( eChanType eType )
|
|
{
|
|
switch( eType )
|
|
{
|
|
case CHN_8U:
|
|
return GDT_Byte;
|
|
|
|
case CHN_16U:
|
|
return GDT_UInt16;
|
|
|
|
case CHN_16S:
|
|
return GDT_Int16;
|
|
|
|
case CHN_32R:
|
|
return GDT_Float32;
|
|
|
|
case CHN_BIT:
|
|
return GDT_Byte;
|
|
|
|
case CHN_C16U:
|
|
return GDT_CInt16;
|
|
|
|
case CHN_C16S:
|
|
return GDT_CInt16;
|
|
|
|
case CHN_C32R:
|
|
return GDT_CFloat32;
|
|
|
|
default:
|
|
return GDT_Unknown;
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Identify() */
|
|
/************************************************************************/
|
|
|
|
int PCIDSK2Dataset::Identify( GDALOpenInfo * poOpenInfo )
|
|
{
|
|
if( poOpenInfo->nHeaderBytes < 512
|
|
|| !EQUALN((const char *) poOpenInfo->pabyHeader, "PCIDSK ", 8) )
|
|
return FALSE;
|
|
else
|
|
return TRUE;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Open() */
|
|
/************************************************************************/
|
|
|
|
GDALDataset *PCIDSK2Dataset::Open( GDALOpenInfo * poOpenInfo )
|
|
{
|
|
if( !Identify( poOpenInfo ) )
|
|
return NULL;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Try opening the file. */
|
|
/* -------------------------------------------------------------------- */
|
|
try {
|
|
PCIDSKFile *poFile =
|
|
PCIDSK::Open( poOpenInfo->pszFilename,
|
|
poOpenInfo->eAccess == GA_ReadOnly ? "r" : "r+",
|
|
PCIDSK2GetInterfaces() );
|
|
if( poFile == NULL )
|
|
{
|
|
CPLError( CE_Failure, CPLE_OpenFailed,
|
|
"Failed to re-open %s within PCIDSK driver.\n",
|
|
poOpenInfo->pszFilename );
|
|
return NULL;
|
|
}
|
|
|
|
/* Check if this is a vector-only PCIDSK file and that we are */
|
|
/* opened in raster-only mode */
|
|
if( poOpenInfo->eAccess == GA_ReadOnly &&
|
|
(poOpenInfo->nOpenFlags & GDAL_OF_RASTER) != 0 &&
|
|
(poOpenInfo->nOpenFlags & GDAL_OF_VECTOR) == 0 &&
|
|
poFile->GetChannels() == 0 &&
|
|
poFile->GetSegment( PCIDSK::SEG_VEC, "" ) != NULL )
|
|
{
|
|
CPLDebug("PCIDSK", "This is a vector-only PCIDSK dataset, "
|
|
"but it has been opened in read-only in raster-only mode");
|
|
delete poFile;
|
|
return NULL;
|
|
}
|
|
/* Reverse test */
|
|
if( poOpenInfo->eAccess == GA_ReadOnly &&
|
|
(poOpenInfo->nOpenFlags & GDAL_OF_RASTER) == 0 &&
|
|
(poOpenInfo->nOpenFlags & GDAL_OF_VECTOR) != 0 &&
|
|
poFile->GetChannels() != 0 &&
|
|
poFile->GetSegment( PCIDSK::SEG_VEC, "" ) == NULL )
|
|
{
|
|
CPLDebug("PCIDSK", "This is a raster-only PCIDSK dataset, "
|
|
"but it has been opened in read-only in vector-only mode");
|
|
delete poFile;
|
|
return NULL;
|
|
}
|
|
|
|
return LLOpen( poOpenInfo->pszFilename, poFile, poOpenInfo->eAccess,
|
|
poOpenInfo->GetSiblingFiles() );
|
|
}
|
|
/* -------------------------------------------------------------------- */
|
|
/* Trap exceptions. */
|
|
/* -------------------------------------------------------------------- */
|
|
catch( PCIDSKException ex )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"%s", ex.what() );
|
|
return NULL;
|
|
}
|
|
catch( ... )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"PCIDSK::Create() failed, unexpected exception." );
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* LLOpen() */
|
|
/* */
|
|
/* Low level variant of open that takes the preexisting */
|
|
/* PCIDSKFile. */
|
|
/************************************************************************/
|
|
|
|
GDALDataset *PCIDSK2Dataset::LLOpen( const char *pszFilename,
|
|
PCIDSK::PCIDSKFile *poFile,
|
|
GDALAccess eAccess,
|
|
char** papszSiblingFiles )
|
|
|
|
{
|
|
PCIDSK2Dataset *poDS = NULL;
|
|
try {
|
|
/* -------------------------------------------------------------------- */
|
|
/* Create a corresponding GDALDataset. */
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
poDS = new PCIDSK2Dataset();
|
|
|
|
poDS->poFile = poFile;
|
|
poDS->eAccess = eAccess;
|
|
poDS->nRasterXSize = poFile->GetWidth();
|
|
poDS->nRasterYSize = poFile->GetHeight();
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Are we specifically PIXEL or BAND interleaving? */
|
|
/* */
|
|
/* We don't set anything for FILE since it is harder to know if */
|
|
/* this is tiled or what the on disk interleaving is. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( EQUAL(poFile->GetInterleaving().c_str(),"PIXEL") )
|
|
poDS->SetMetadataItem( "IMAGE_STRUCTURE", "PIXEL",
|
|
"IMAGE_STRUCTURE" );
|
|
else if( EQUAL(poFile->GetInterleaving().c_str(),"BAND") )
|
|
poDS->SetMetadataItem( "IMAGE_STRUCTURE", "BAND",
|
|
"IMAGE_STRUCTURE" );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Create band objects. */
|
|
/* -------------------------------------------------------------------- */
|
|
int iBand;
|
|
|
|
for( iBand = 0; iBand < poFile->GetChannels(); iBand++ )
|
|
{
|
|
PCIDSKChannel* poChannel = poFile->GetChannel( iBand + 1 );
|
|
if (poChannel->GetBlockWidth() <= 0 ||
|
|
poChannel->GetBlockHeight() <= 0)
|
|
{
|
|
delete poDS;
|
|
return NULL;
|
|
}
|
|
|
|
poDS->SetBand( iBand+1, new PCIDSK2Band( poDS, poFile, iBand+1 ));
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Create band objects for bitmap segments. */
|
|
/* -------------------------------------------------------------------- */
|
|
int nLastBitmapSegment = 0;
|
|
PCIDSKSegment *poBitSeg;
|
|
|
|
while( (poBitSeg = poFile->GetSegment( SEG_BIT, "",
|
|
nLastBitmapSegment)) != NULL )
|
|
{
|
|
PCIDSKChannel *poChannel =
|
|
dynamic_cast<PCIDSKChannel*>( poBitSeg );
|
|
if (poChannel->GetBlockWidth() <= 0 ||
|
|
poChannel->GetBlockHeight() <= 0)
|
|
{
|
|
delete poDS;
|
|
return NULL;
|
|
}
|
|
|
|
poDS->SetBand( poDS->GetRasterCount()+1,
|
|
new PCIDSK2Band( poChannel ) );
|
|
|
|
nLastBitmapSegment = poBitSeg->GetSegmentNumber();
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Create vector layers from vector segments. */
|
|
/* -------------------------------------------------------------------- */
|
|
PCIDSK::PCIDSKSegment *segobj;
|
|
for( segobj = poFile->GetSegment( PCIDSK::SEG_VEC, "" );
|
|
segobj != NULL;
|
|
segobj = poFile->GetSegment( PCIDSK::SEG_VEC, "",
|
|
segobj->GetSegmentNumber() ) )
|
|
{
|
|
poDS->apoLayers.push_back( new OGRPCIDSKLayer( segobj, eAccess == GA_Update ) );
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Process RPC segment, if there is one. */
|
|
/* -------------------------------------------------------------------- */
|
|
poDS->ProcessRPC();
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Initialize any PAM information. */
|
|
/* -------------------------------------------------------------------- */
|
|
poDS->SetDescription( pszFilename );
|
|
poDS->TryLoadXML( papszSiblingFiles );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Open overviews. */
|
|
/* -------------------------------------------------------------------- */
|
|
poDS->oOvManager.Initialize( poDS, pszFilename, papszSiblingFiles );
|
|
|
|
return( poDS );
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Trap exceptions. */
|
|
/* -------------------------------------------------------------------- */
|
|
catch( PCIDSKException ex )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"%s", ex.what() );
|
|
}
|
|
catch( ... )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"PCIDSK SDK Failure in Open(), unexpected exception." );
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* In case of exception, close dataset */
|
|
/* -------------------------------------------------------------------- */
|
|
delete poDS;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Create() */
|
|
/************************************************************************/
|
|
|
|
GDALDataset *PCIDSK2Dataset::Create( const char * pszFilename,
|
|
int nXSize, int nYSize, int nBands,
|
|
GDALDataType eType,
|
|
char **papszParmList )
|
|
|
|
{
|
|
PCIDSKFile *poFile;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Prepare channel type list. */
|
|
/* -------------------------------------------------------------------- */
|
|
std::vector<eChanType> aeChanTypes;
|
|
|
|
if( eType == GDT_Float32 )
|
|
aeChanTypes.resize( MAX(1,nBands), CHN_32R );
|
|
else if( eType == GDT_Int16 )
|
|
aeChanTypes.resize( MAX(1,nBands), CHN_16S );
|
|
else if( eType == GDT_UInt16 )
|
|
aeChanTypes.resize( MAX(1,nBands), CHN_16U );
|
|
else if( eType == GDT_CInt16 )
|
|
aeChanTypes.resize( MAX(1, nBands), CHN_C16S );
|
|
else if( eType == GDT_CFloat32 )
|
|
aeChanTypes.resize( MAX(1, nBands), CHN_C32R );
|
|
else
|
|
aeChanTypes.resize( MAX(1,nBands), CHN_8U );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Reformat options. Currently no support for jpeg compression */
|
|
/* quality. */
|
|
/* -------------------------------------------------------------------- */
|
|
CPLString osOptions;
|
|
const char *pszValue;
|
|
|
|
pszValue = CSLFetchNameValue( papszParmList, "INTERLEAVING" );
|
|
if( pszValue == NULL )
|
|
pszValue = "BAND";
|
|
|
|
osOptions = pszValue;
|
|
|
|
if( osOptions == "TILED" )
|
|
{
|
|
pszValue = CSLFetchNameValue( papszParmList, "TILESIZE" );
|
|
if( pszValue != NULL )
|
|
osOptions += pszValue;
|
|
|
|
pszValue = CSLFetchNameValue( papszParmList, "COMPRESSION" );
|
|
if( pszValue != NULL )
|
|
{
|
|
osOptions += " ";
|
|
osOptions += pszValue;
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Try creation. */
|
|
/* -------------------------------------------------------------------- */
|
|
try {
|
|
if( nBands == 0 )
|
|
nXSize = nYSize = 512;
|
|
poFile = PCIDSK::Create( pszFilename, nXSize, nYSize, nBands,
|
|
&(aeChanTypes[0]), osOptions,
|
|
PCIDSK2GetInterfaces() );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Apply band descriptions, if provided as creation options. */
|
|
/* -------------------------------------------------------------------- */
|
|
size_t i;
|
|
|
|
for( i = 0; papszParmList != NULL && papszParmList[i] != NULL; i++ )
|
|
{
|
|
if( EQUALN(papszParmList[i],"BANDDESC",8) )
|
|
{
|
|
int nBand = atoi(papszParmList[i] + 8 );
|
|
const char *pszDescription = strstr(papszParmList[i],"=");
|
|
if( pszDescription && nBand > 0 && nBand <= nBands )
|
|
{
|
|
poFile->GetChannel(nBand)->SetDescription( pszDescription+1 );
|
|
}
|
|
}
|
|
}
|
|
|
|
return LLOpen( pszFilename, poFile, GA_Update );
|
|
}
|
|
/* -------------------------------------------------------------------- */
|
|
/* Trap exceptions. */
|
|
/* -------------------------------------------------------------------- */
|
|
catch( PCIDSKException ex )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"%s", ex.what() );
|
|
return NULL;
|
|
}
|
|
catch( ... )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"PCIDSK::Create() failed, unexpected exception." );
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* TestCapability() */
|
|
/************************************************************************/
|
|
|
|
int PCIDSK2Dataset::TestCapability( const char * pszCap )
|
|
|
|
{
|
|
if( EQUAL(pszCap,ODsCCreateLayer) )
|
|
return eAccess == GA_Update;
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetLayer() */
|
|
/************************************************************************/
|
|
|
|
OGRLayer *PCIDSK2Dataset::GetLayer( int iLayer )
|
|
|
|
{
|
|
if( iLayer < 0 || iLayer >= (int) apoLayers.size() )
|
|
return NULL;
|
|
else
|
|
return apoLayers[iLayer];
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* ICreateLayer() */
|
|
/************************************************************************/
|
|
|
|
OGRLayer *
|
|
PCIDSK2Dataset::ICreateLayer( const char * pszLayerName,
|
|
OGRSpatialReference *poSRS,
|
|
OGRwkbGeometryType eType,
|
|
CPL_UNUSED char ** papszOptions )
|
|
{
|
|
/* -------------------------------------------------------------------- */
|
|
/* Verify we are in update mode. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( eAccess != GA_Update )
|
|
{
|
|
CPLError( CE_Failure, CPLE_NoWriteAccess,
|
|
"Data source %s opened read-only.\n"
|
|
"New layer %s cannot be created.\n",
|
|
GetDescription(), pszLayerName );
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Figure out what type of layer we need. */
|
|
/* -------------------------------------------------------------------- */
|
|
std::string osLayerType;
|
|
|
|
switch( wkbFlatten(eType) )
|
|
{
|
|
case wkbPoint:
|
|
osLayerType = "POINTS";
|
|
break;
|
|
|
|
case wkbLineString:
|
|
osLayerType = "ARCS";
|
|
break;
|
|
|
|
case wkbPolygon:
|
|
osLayerType = "WHOLE_POLYGONS";
|
|
break;
|
|
|
|
case wkbNone:
|
|
osLayerType = "TABLE";
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Create the segment. */
|
|
/* -------------------------------------------------------------------- */
|
|
int nSegNum = poFile->CreateSegment( pszLayerName, "",
|
|
PCIDSK::SEG_VEC, 0L );
|
|
PCIDSK::PCIDSKSegment *poSeg = poFile->GetSegment( nSegNum );
|
|
PCIDSK::PCIDSKVectorSegment *poVecSeg =
|
|
dynamic_cast<PCIDSK::PCIDSKVectorSegment*>( poSeg );
|
|
|
|
if( osLayerType != "" )
|
|
poSeg->SetMetadataValue( "LAYER_TYPE", osLayerType );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Do we need to apply a coordinate system? */
|
|
/* -------------------------------------------------------------------- */
|
|
char *pszGeosys = NULL;
|
|
char *pszUnits = NULL;
|
|
double *padfPrjParams = NULL;
|
|
|
|
if( poSRS != NULL
|
|
&& poSRS->exportToPCI( &pszGeosys, &pszUnits,
|
|
&padfPrjParams ) == OGRERR_NONE )
|
|
{
|
|
try
|
|
{
|
|
std::vector<double> adfPCIParameters;
|
|
int i;
|
|
|
|
for( i = 0; i < 17; i++ )
|
|
adfPCIParameters.push_back( padfPrjParams[i] );
|
|
|
|
if( EQUALN(pszUnits,"FOOT",4) )
|
|
adfPCIParameters.push_back(
|
|
(double)(int) PCIDSK::UNIT_US_FOOT );
|
|
else if( EQUALN(pszUnits,"INTL FOOT",9) )
|
|
adfPCIParameters.push_back(
|
|
(double)(int) PCIDSK::UNIT_INTL_FOOT );
|
|
else if( EQUALN(pszUnits,"DEGREE",6) )
|
|
adfPCIParameters.push_back(
|
|
(double)(int) PCIDSK::UNIT_DEGREE );
|
|
else
|
|
adfPCIParameters.push_back(
|
|
(double)(int) PCIDSK::UNIT_METER );
|
|
|
|
poVecSeg->SetProjection( pszGeosys, adfPCIParameters );
|
|
}
|
|
catch( PCIDSK::PCIDSKException ex )
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"%s", ex.what() );
|
|
}
|
|
|
|
CPLFree( pszGeosys );
|
|
CPLFree( pszUnits );
|
|
CPLFree( padfPrjParams );
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Create the layer object. */
|
|
/* -------------------------------------------------------------------- */
|
|
apoLayers.push_back( new OGRPCIDSKLayer( poSeg, TRUE ) );
|
|
|
|
return apoLayers[apoLayers.size()-1];
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALRegister_PCIDSK() */
|
|
/************************************************************************/
|
|
|
|
void GDALRegister_PCIDSK()
|
|
|
|
{
|
|
GDALDriver *poDriver;
|
|
|
|
if( GDALGetDriverByName( "PCIDSK" ) == NULL )
|
|
{
|
|
poDriver = new GDALDriver();
|
|
|
|
poDriver->SetDescription( "PCIDSK" );
|
|
poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
|
|
poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
|
|
poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
|
|
"PCIDSK Database File" );
|
|
poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
|
|
"frmt_pcidsk.html" );
|
|
poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
|
|
poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "pix" );
|
|
poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte UInt16 Int16 Float32 CInt16 CFloat32" );
|
|
poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
|
|
"<CreationOptionList>"
|
|
" <Option name='INTERLEAVING' type='string-select' default='BAND' description='raster data organization'>"
|
|
" <Value>PIXEL</Value>"
|
|
" <Value>BAND</Value>"
|
|
" <Value>FILE</Value>"
|
|
" <Value>TILED</Value>"
|
|
" </Option>"
|
|
" <Option name='COMPRESSION' type='string-select' default='NONE' description='compression - (INTERLEAVING=TILED only)'>"
|
|
" <Value>NONE</Value>"
|
|
" <Value>RLE</Value>"
|
|
" <Value>JPEG</Value>"
|
|
" </Option>"
|
|
" <Option name='TILESIZE' type='int' default='127' description='Tile Size (INTERLEAVING=TILED only)'/>"
|
|
"</CreationOptionList>" );
|
|
poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST, "<LayerCreationOptionList/>" );
|
|
|
|
poDriver->pfnIdentify = PCIDSK2Dataset::Identify;
|
|
poDriver->pfnOpen = PCIDSK2Dataset::Open;
|
|
poDriver->pfnCreate = PCIDSK2Dataset::Create;
|
|
|
|
GetGDALDriverManager()->RegisterDriver( poDriver );
|
|
}
|
|
}
|