ultimatepp/bazaar/plugin/gdal/frmts/georaster/georaster_wrapper.cpp
cxl 23ff1e7e82 .gdal moved to bazaar
git-svn-id: svn://ultimatepp.org/upp/trunk@9273 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2015-12-07 13:36:24 +00:00

3990 lines
125 KiB
C++

/******************************************************************************
* $Id: $
*
* Name: georaster_wrapper.cpp
* Project: Oracle Spatial GeoRaster Driver
* Purpose: Implement GeoRasterWrapper methods
* Author: Ivan Lucena [ivan.lucena at oracle.com]
*
******************************************************************************
* Copyright (c) 2008, Ivan Lucena
*
* 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 <string.h>
#include "georaster_priv.h"
#include "cpl_error.h"
#include "cpl_string.h"
#include "cpl_minixml.h"
// ---------------------------------------------------------------------------
// GeoRasterWrapper()
// ---------------------------------------------------------------------------
GeoRasterWrapper::GeoRasterWrapper()
{
nRasterId = -1;
phMetadata = NULL;
nRasterRows = 0;
nRasterColumns = 0;
nRasterBands = 0;
nRowBlockSize = 0;
nColumnBlockSize = 0;
nBandBlockSize = 0;
nTotalColumnBlocks = 0;
nTotalRowBlocks = 0;
nTotalBandBlocks = 0;
nCellSizeBits = 0;
nGDALCellBytes = 0;
dfXCoefficient[0] = 1.0;
dfXCoefficient[1] = 0.0;
dfXCoefficient[2] = 0.0;
dfYCoefficient[0] = 0.0;
dfYCoefficient[1] = 1.0;
dfYCoefficient[2] = 0.0;
sCompressionType = "NONE";
nCompressQuality = 75;
bGenPyramid = false;
nPyramidLevels = 0;
sPyramidResampling = "NN";
pahLocator = NULL;
pabyBlockBuf = NULL;
pabyCompressBuf = NULL;
bIsReferenced = false;
poBlockStmt = NULL;
nCacheBlockId = -1;
nCurrentLevel = -1;
pahLevels = NULL;
nLevelOffset = 0L;
sInterleaving = "BSQ";
bUpdate = false;
bInitializeIO = false;
bFlushMetadata = false;
nSRID = 0;
nExtentSRID = 0;
bGenSpatialIndex = false;
bCreateObjectTable = false;
nPyramidMaxLevel = 0;
nBlockCount = 0L;
nGDALBlockBytes = 0L;
sDInfo.global_state = 0;
sCInfo.global_state = 0;
bHasBitmapMask = false;
nBlockBytes = 0L;
bFlushBlock = false;
nFlushBlockSize = 0L;
bUniqueFound = false;
sValueAttributeTab = "";
psNoDataList = NULL;
bWriteOnly = false;
bBlocking = true;
bAutoBlocking = false;
eModelCoordLocation = MCL_DEFAULT;
phRPC = NULL;
}
// ---------------------------------------------------------------------------
// GeoRasterDataset()
// ---------------------------------------------------------------------------
GeoRasterWrapper::~GeoRasterWrapper()
{
FlushMetadata();
if( pahLocator && nBlockCount )
{
OWStatement::Free( pahLocator, nBlockCount );
}
CPLFree( pahLocator );
CPLFree( pabyBlockBuf );
CPLFree( pabyCompressBuf );
CPLFree( pahLevels );
if( CPLListCount( psNoDataList ) )
{
CPLList* psList = NULL;
for( psList = psNoDataList; psList ; psList = psList->psNext )
{
CPLFree( psList->pData );
}
CPLListDestroy( psNoDataList );
}
if( poBlockStmt )
{
delete poBlockStmt;
}
CPLDestroyXMLNode( phMetadata );
if( sDInfo.global_state )
{
jpeg_destroy_decompress( &sDInfo );
}
if( sCInfo.global_state )
{
jpeg_destroy_compress( &sCInfo );
}
if( poConnection )
{
delete poConnection;
}
if( phRPC )
{
CPLFree( phRPC );
}
}
// ---------------------------------------------------------------------------
// ParseIdentificator()
// ---------------------------------------------------------------------------
//
// StringID:
// {georaster,geor}:<name>{/,,}<password>{/,@}<db>,<tab>,<col>,<where>
// {georaster,geor}:<name>{/,,}<password>{/,@}<db>,<rdt>,<rid>
//
// ---------------------------------------------------------------------------
char** GeoRasterWrapper::ParseIdentificator( const char* pszStringID )
{
char* pszStartPos = (char*) strstr( pszStringID, ":" ) + 1;
char** papszParam = CSLTokenizeString2( pszStartPos, ",@",
CSLT_HONOURSTRINGS | CSLT_ALLOWEMPTYTOKENS |
CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
// -------------------------------------------------------------------
// The "/" should not be catch on the previous parser
// -------------------------------------------------------------------
if( CSLCount( papszParam ) > 0 )
{
char** papszFirst2 = CSLTokenizeString2( papszParam[0], "/",
CSLT_HONOURSTRINGS | CSLT_ALLOWEMPTYTOKENS );
if( CSLCount( papszFirst2 ) == 2 )
{
papszParam = CSLInsertStrings( papszParam, 0, papszFirst2 );
papszParam = CSLRemoveStrings( papszParam, 2, 1, NULL );
}
CSLDestroy( papszFirst2 );
}
return papszParam;
}
// ---------------------------------------------------------------------------
// Open()
// ---------------------------------------------------------------------------
GeoRasterWrapper* GeoRasterWrapper::Open( const char* pszStringId, bool bUpdate )
{
char** papszParam = ParseIdentificator( pszStringId );
// ---------------------------------------------------------------
// Validate identificator
// ---------------------------------------------------------------
int nArgc = CSLCount( papszParam );
for( ; nArgc < 3; nArgc++ )
{
papszParam = CSLAddString( papszParam, "" );
}
// ---------------------------------------------------------------
// Create a GeoRasterWrapper object
// ---------------------------------------------------------------
GeoRasterWrapper* poGRW = new GeoRasterWrapper();
if( ! poGRW )
{
return NULL;
}
poGRW->bUpdate = bUpdate;
// ---------------------------------------------------------------
// Get a connection with Oracle server
// ---------------------------------------------------------------
poGRW->poConnection = new OWConnection( papszParam[0],
papszParam[1],
papszParam[2] );
if( ! poGRW->poConnection->Succeeded() )
{
CSLDestroy( papszParam );
delete poGRW;
return NULL;
}
// -------------------------------------------------------------------
// Extract schema name
// -------------------------------------------------------------------
if( nArgc > 3 )
{
char** papszSchema = CSLTokenizeString2( papszParam[3], ".",
CSLT_HONOURSTRINGS | CSLT_ALLOWEMPTYTOKENS );
if( CSLCount( papszSchema ) == 2 )
{
poGRW->sOwner = papszSchema[0];
poGRW->sSchema = CPLSPrintf( "%s.", poGRW->sOwner.c_str() );
papszParam = CSLRemoveStrings( papszParam, 3, 1, NULL );
if( ! EQUAL( papszSchema[1], "" ) )
{
papszParam = CSLInsertString( papszParam, 3, papszSchema[1] );
}
nArgc = CSLCount( papszParam );
}
else
{
poGRW->sSchema = "";
poGRW->sOwner = poGRW->poConnection->GetUser();
}
CSLDestroy( papszSchema );
}
else
{
poGRW->sSchema = "";
poGRW->sOwner = poGRW->poConnection->GetUser();
}
// -------------------------------------------------------------------
// Assign parameters from Identification string
// -------------------------------------------------------------------
switch( nArgc )
{
case 6 :
poGRW->sTable = papszParam[3];
poGRW->sColumn = papszParam[4];
poGRW->sWhere = papszParam[5];
break;
case 5 :
if( OWIsNumeric( papszParam[4] ) )
{
poGRW->sDataTable = papszParam[3];
poGRW->nRasterId = atoi( papszParam[4]);
break;
}
else
{
poGRW->sTable = papszParam[3];
poGRW->sColumn = papszParam[4];
return poGRW;
}
case 4 :
poGRW->sTable = papszParam[3];
return poGRW;
default :
return poGRW;
}
CSLDestroy( papszParam );
// -------------------------------------------------------------------
// Query all the basic information at once to reduce round trips
// -------------------------------------------------------------------
char szOwner[OWCODE];
char szTable[OWCODE];
char szColumn[OWTEXT];
char szDataTable[OWCODE];
char szWhere[OWTEXT];
int nRasterId = -1;
int nSizeX = 0;
int nSizeY = 0;
int nSRID = 0;
OCILobLocator* phLocator = NULL;
double dfULx = 0.0;
double dfURx = 0.0;
double dfLRx = 0.0;
double dfULy = 0.0;
double dfLLy = 0.0;
double dfLRy = 0.0;
char szWKText[3 * OWTEXT];
char szAuthority[OWTEXT];
char szMLC[OWTEXT];
szOwner[0] = '\0';
szTable[0] = '\0';
szColumn[0] = '\0';
szDataTable[0] = '\0';
szWhere[0] = '\0';
szWKText[0] = '\0';
szAuthority[0] = '\0';
szMLC[0] = '\0';
if( ! poGRW->sOwner.empty() )
{
strcpy( szOwner, poGRW->sOwner.c_str() );
}
if( ! poGRW->sTable.empty() )
{
strcpy( szTable, poGRW->sTable.c_str() );
}
if( ! poGRW->sColumn.empty() )
{
strcpy( szColumn, poGRW->sColumn.c_str() );
}
if( ! poGRW->sDataTable.empty() )
{
strcpy( szDataTable, poGRW->sDataTable.c_str() );
}
nRasterId = poGRW->nRasterId;
if( ! poGRW->sWhere.empty() )
{
strcpy( szWhere, poGRW->sWhere.c_str() );
}
OWStatement* poStmt = poGRW->poConnection->CreateStatement(
"DECLARE\n"
" SCM VARCHAR2(64) := 'xmlns=\"http://xmlns.oracle.com/spatial/georaster\"';\n"
" GUL SDO_GEOMETRY := null;\n"
" GUR SDO_GEOMETRY := null;\n"
" GLL SDO_GEOMETRY := null;\n"
" GLR SDO_GEOMETRY := null;\n"
"BEGIN\n"
"\n"
" IF :datatable IS NOT NULL AND :rasterid > 0 THEN\n"
"\n"
" EXECUTE IMMEDIATE\n"
" 'SELECT OWNER, TABLE_NAME, COLUMN_NAME\n"
" FROM ALL_SDO_GEOR_SYSDATA\n"
" WHERE RDT_TABLE_NAME = UPPER(:1)\n"
" AND RASTER_ID = :2'\n"
" INTO :owner, :table, :column\n"
" USING :datatable, :rasterid;\n"
"\n"
" EXECUTE IMMEDIATE\n"
" 'SELECT T.'||:column||'.METADATA.getClobVal()\n"
" FROM '||:owner||'.'||:table||' T\n"
" WHERE T.'||:column||'.RASTERDATATABLE = UPPER(:1)\n"
" AND T.'||:column||'.RASTERID = :2'\n"
" INTO :metadata\n"
" USING :datatable, :rasterid;\n"
" :counter := 1;\n"
"\n"
" ELSE\n"
"\n"
" EXECUTE IMMEDIATE\n"
" 'SELECT T.'||:column||'.RASTERDATATABLE,\n"
" T.'||:column||'.RASTERID,\n"
" T.'||:column||'.METADATA.getClobVal()\n"
" FROM '||:owner||'.'||:table||' T\n"
" WHERE '||:where\n"
" INTO :datatable, :rasterid, :metadata;\n"
" :counter := 1;\n"
"\n"
" END IF;\n"
"\n"
" SELECT\n"
" extractValue(XMLType(:metadata),"
"'/georasterMetadata/rasterInfo/dimensionSize[@type=\"ROW\"]/size', "
"SCM),\n"
" extractValue(XMLType(:metadata),"
"'/georasterMetadata/rasterInfo/dimensionSize[@type=\"COLUMN\"]/size', "
"SCM),\n"
" extractValue(XMLType(:metadata),"
"'/georasterMetadata/spatialReferenceInfo/SRID', "
"SCM),\n"
" extractValue(XMLType(:metadata),"
"'/georasterMetadata/spatialReferenceInfo/modelCoordinateLocation', "
"SCM)\n"
" INTO :sizey, :sizex, :srid, :mcl FROM DUAL;\n"
"\n"
" EXECUTE IMMEDIATE\n"
" 'SELECT\n"
" SDO_GEOR.getModelCoordinate('||:column||', 0, "
"SDO_NUMBER_ARRAY(0, 0)),\n"
" SDO_GEOR.getModelCoordinate('||:column||', 0, "
"SDO_NUMBER_ARRAY(0, '||:sizex||')),\n"
" SDO_GEOR.getModelCoordinate('||:column||', 0, "
"SDO_NUMBER_ARRAY('||:sizey||', 0)),\n"
" SDO_GEOR.getModelCoordinate('||:column||', 0, "
"SDO_NUMBER_ARRAY('||:sizey||', '||:sizex||'))\n"
" FROM '||:owner||'.'||:table||' T\n"
" WHERE T.'||:column||'.RASTERDATATABLE = UPPER(:1)\n"
" AND T.'||:column||'.RASTERID = :2'\n"
" INTO GUL, GLL, GUR, GLR\n"
" USING :datatable, :rasterid;\n"
"\n"
" :ULx := GUL.sdo_point.x;\n"
" :URx := GUR.sdo_point.x;\n"
" :LRx := GLR.sdo_point.x;\n"
" :ULy := GUL.sdo_point.y;\n"
" :LLy := GLL.sdo_point.y;\n"
" :LRy := GLR.sdo_point.y;\n"
"\n"
" BEGIN\n"
" EXECUTE IMMEDIATE\n"
" 'SELECT WKTEXT, AUTH_NAME\n"
" FROM MDSYS.CS_SRS\n"
" WHERE SRID = :1 AND WKTEXT IS NOT NULL'\n"
" INTO :wktext, :authority\n"
" USING :srid;\n"
" EXCEPTION\n"
" WHEN no_data_found THEN\n"
" :wktext := '';\n"
" :authority := '';\n"
" END;\n"
"\n"
" EXCEPTION\n"
" WHEN no_data_found THEN :counter := 0;\n"
" WHEN too_many_rows THEN :counter := 2;\n"
"END;" );
int nCounter = 0;
poStmt->BindName( ":datatable", szDataTable );
poStmt->BindName( ":rasterid", &nRasterId );
poStmt->BindName( ":owner", szOwner );
poStmt->BindName( ":table", szTable );
poStmt->BindName( ":column", szColumn );
poStmt->BindName( ":where", szWhere );
poStmt->BindName( ":counter", &nCounter );
poStmt->BindName( ":metadata", &phLocator );
poStmt->BindName( ":sizex", &nSizeX );
poStmt->BindName( ":sizey", &nSizeY );
poStmt->BindName( ":srid", &nSRID );
poStmt->BindName( ":mcl", szMLC );
poStmt->BindName( ":ULx", &dfULx );
poStmt->BindName( ":URx", &dfURx );
poStmt->BindName( ":LRx", &dfLRx );
poStmt->BindName( ":ULy", &dfULy );
poStmt->BindName( ":LLy", &dfLLy );
poStmt->BindName( ":LRy", &dfLRy );
poStmt->BindName( ":wktext", szWKText, sizeof(szWKText) );
poStmt->BindName( ":authority", szAuthority );
CPLErrorReset();
if( ! poStmt->Execute() )
{
delete poStmt;
delete poGRW;
return NULL;
}
if( nCounter < 1 )
{
delete poStmt;
delete poGRW;
return NULL;
}
poGRW->sSchema = CPLSPrintf( "%s.", szOwner );
poGRW->sOwner = szOwner;
poGRW->sTable = szTable;
poGRW->sColumn = szColumn;
if( nCounter == 1 )
{
poGRW->bUniqueFound = true;
}
else
{
poGRW->bUniqueFound = false;
delete poStmt;
return poGRW;
}
poGRW->sWKText = szWKText;
poGRW->sAuthority = szAuthority;
poGRW->sDataTable = szDataTable;
poGRW->nRasterId = nRasterId;
poGRW->sWhere = CPLSPrintf(
"T.%s.RASTERDATATABLE = UPPER('%s') AND T.%s.RASTERID = %d",
poGRW->sColumn.c_str(),
poGRW->sDataTable.c_str(),
poGRW->sColumn.c_str(),
poGRW->nRasterId );
// -------------------------------------------------------------------
// Read Metadata XML in text
// -------------------------------------------------------------------
char* pszXML = poStmt->ReadCLob( phLocator );
if( pszXML )
{
// -----------------------------------------------------------
// Get basic information from xml metadata
// -----------------------------------------------------------
poGRW->phMetadata = CPLParseXMLString( pszXML );
poGRW->GetRasterInfo();
}
else
{
poGRW->sDataTable = "";
poGRW->nRasterId = 0;
}
// --------------------------------------------------------------------
// Load Coefficients matrix
// --------------------------------------------------------------------
if ( EQUAL( szMLC, "UPPERLEFT" ) )
{
poGRW->eModelCoordLocation = MCL_UPPERLEFT;
}
else
{
poGRW->eModelCoordLocation = MCL_DEFAULT;
}
double dfRotation = 0.0;
if( ! CPLIsEqual( dfULy, dfLLy ) )
{
dfRotation = ( dfURx - dfULx ) / ( dfLLy - dfULy );
}
poGRW->dfXCoefficient[0] = ( dfLRx - dfULx ) / nSizeX;
poGRW->dfXCoefficient[1] = dfRotation;
poGRW->dfXCoefficient[2] = dfULx;
poGRW->dfYCoefficient[0] = -dfRotation;
poGRW->dfYCoefficient[1] = ( dfLRy - dfULy ) / nSizeY;
poGRW->dfYCoefficient[2] = dfULy;
if ( poGRW->eModelCoordLocation == MCL_CENTER )
{
poGRW->dfXCoefficient[2] -= poGRW->dfXCoefficient[0] / 2;
poGRW->dfYCoefficient[2] -= poGRW->dfYCoefficient[1] / 2;
CPLDebug("GEOR","eModelCoordLocation = MCL_CENTER");
}
else
{
CPLDebug("GEOR","eModelCoordLocation = MCL_UPPERLEFT");
}
// -------------------------------------------------------------------
// Apply ULTCoordinate
// -------------------------------------------------------------------
poGRW->dfXCoefficient[2] +=
( poGRW->anULTCoordinate[0] * poGRW->dfXCoefficient[0] );
poGRW->dfYCoefficient[2] +=
( poGRW->anULTCoordinate[1] * poGRW->dfYCoefficient[1] );
// -------------------------------------------------------------------
// Clean up
// -------------------------------------------------------------------
OCIDescriptorFree( phLocator, OCI_DTYPE_LOB );
CPLFree( pszXML );
delete poStmt;
// -------------------------------------------------------------------
// Return a GeoRasterWrapper object
// -------------------------------------------------------------------
return poGRW;
}
// ---------------------------------------------------------------------------
// Create()
// ---------------------------------------------------------------------------
bool GeoRasterWrapper::Create( char* pszDescription,
char* pszInsert,
bool bUpdate )
{
CPLString sValues;
CPLString sFormat;
if( sTable.empty() ||
sColumn.empty() )
{
return false;
}
// -------------------------------------------------------------------
// Parse RDT/RID from the current szValues
// -------------------------------------------------------------------
char szRDT[OWNAME];
char szRID[OWCODE];
if( ! sDataTable.empty() )
{
strcpy( szRDT, CPLSPrintf( "'%s'", sDataTable.c_str() ) );
}
else
{
strcpy( szRDT, OWParseSDO_GEOR_INIT( sValues.c_str(), 1 ) );
}
if ( nRasterId > 0 )
{
strcpy( szRID, CPLSPrintf( "%d", nRasterId ) );
}
else
{
strcpy( szRID, OWParseSDO_GEOR_INIT( sValues.c_str(), 2 ) );
if ( EQUAL( szRID, "" ) )
{
strcpy( szRID, "NULL" );
}
}
// -------------------------------------------------------------------
// Description parameters
// -------------------------------------------------------------------
char szDescription[OWTEXT];
if( bUpdate == false )
{
if ( pszDescription )
{
strcpy( szDescription, pszDescription );
}
else
{
strcpy( szDescription, CPLSPrintf(
"(%s MDSYS.SDO_GEORASTER)", sColumn.c_str() ) );
}
// ---------------------------------------------------------------
// Insert parameters
// ---------------------------------------------------------------
if( pszInsert )
{
sValues = pszInsert;
if( pszInsert[0] == '(' && sValues.ifind( "VALUES" ) == std::string::npos )
{
sValues = CPLSPrintf( "VALUES %s", pszInsert );
}
}
else
{
sValues = CPLSPrintf( "VALUES (SDO_GEOR.INIT(%s,%s))", szRDT, szRID );
}
}
// -----------------------------------------------------------
// Storage parameters
// -----------------------------------------------------------
nColumnBlockSize = nColumnBlockSize == 0 ? DEFAULT_BLOCK_COLUMNS : nColumnBlockSize;
nRowBlockSize = nRowBlockSize == 0 ? DEFAULT_BLOCK_ROWS : nRowBlockSize;
nBandBlockSize = nBandBlockSize == 0 ? 1 : nBandBlockSize;
// -----------------------------------------------------------
// Blocking storage parameters
// -----------------------------------------------------------
CPLString sBlocking;
if( bBlocking == true )
{
if( bAutoBlocking == true )
{
int nBlockXSize = nColumnBlockSize;
int nBlockYSize = nRowBlockSize;
int nBlockBSize = nBandBlockSize;
OWStatement* poStmt;
poStmt = poConnection->CreateStatement(
"DECLARE\n"
" dimensionSize sdo_number_array;\n"
" blockSize sdo_number_array;\n"
"BEGIN\n"
" dimensionSize := sdo_number_array(:1, :2, :3);\n"
" blockSize := sdo_number_array(:4, :5, :6);\n"
" sdo_geor_utl.calcOptimizedBlockSize(dimensionSize,blockSize);\n"
" :4 := blockSize(1);\n"
" :5 := blockSize(2);\n"
" :6 := blockSize(3);\n"
"END;" );
poStmt->Bind( &nRasterColumns );
poStmt->Bind( &nRasterRows );
poStmt->Bind( &nRasterBands );
poStmt->Bind( &nBlockXSize );
poStmt->Bind( &nBlockYSize );
poStmt->Bind( &nBlockBSize );
if( poStmt->Execute() )
{
nColumnBlockSize = nBlockXSize;
nRowBlockSize = nBlockYSize;
nBandBlockSize = nBlockBSize;
}
delete poStmt;
}
if( nRasterBands == 1 )
{
sBlocking = CPLSPrintf(
"blockSize=(%d, %d)",
nRowBlockSize,
nColumnBlockSize );
}
else
{
sBlocking = CPLSPrintf(
"blockSize=(%d, %d, %d)",
nRowBlockSize,
nColumnBlockSize,
nBandBlockSize );
}
}
else
{
sBlocking = "blocking=FALSE";
nColumnBlockSize = nRasterColumns;
nRowBlockSize = nRasterRows;
nBandBlockSize = nRasterBands;
}
// -----------------------------------------------------------
// Complete format parameters
// -----------------------------------------------------------
if( poConnection->GetVersion() > 10 )
{
if( nRasterBands == 1 )
{
sFormat = CPLSPrintf(
"20001, '"
"dimSize=(%d,%d) ",
nRasterRows, nRasterColumns );
}
else
{
sFormat = CPLSPrintf(
"21001, '"
"dimSize=(%d,%d,%d) ",
nRasterRows, nRasterColumns, nRasterBands );
}
if( EQUALN( sCompressionType.c_str(), "JPEG", 4 ) )
{
sFormat.append( CPLSPrintf(
"%s "
"cellDepth=%s "
"interleaving=%s "
"compression=%s "
"quality=%d'",
sBlocking.c_str(),
sCellDepth.c_str(),
sInterleaving.c_str(),
sCompressionType.c_str(),
nCompressQuality) );
}
else
{
sFormat.append( CPLSPrintf(
"%s "
"cellDepth=%s "
"interleaving=%s "
"compression=%s'",
sBlocking.c_str(),
sCellDepth.c_str(),
sInterleaving.c_str(),
sCompressionType.c_str() ) );
}
}
else
{
// -------------------------------------------------------
// For versions 10g or older
// -------------------------------------------------------
sFormat = CPLSPrintf(
"%s "
"cellDepth=%s "
"interleaving=%s "
"pyramid=FALSE "
"compression=NONE",
sBlocking.c_str(),
sCellDepth.c_str(),
sInterleaving.c_str() );
}
nTotalColumnBlocks = (int)
( ( nRasterColumns + nColumnBlockSize - 1 ) / nColumnBlockSize );
nTotalRowBlocks = (int)
( ( nRasterRows + nRowBlockSize - 1 ) / nRowBlockSize );
nTotalBandBlocks = (int)
( ( nRasterBands + nBandBlockSize - 1) / nBandBlockSize );
// -------------------------------------------------------------------
// Create Georaster Table if needed
// -------------------------------------------------------------------
OWStatement* poStmt;
if( ! bUpdate )
{
poStmt = poConnection->CreateStatement( CPLSPrintf(
"DECLARE\n"
" TAB VARCHAR2(68) := UPPER('%s');\n"
" COL VARCHAR2(68) := UPPER('%s');\n"
" OWN VARCHAR2(68) := UPPER('%s');\n"
" CNT NUMBER := 0;\n"
"BEGIN\n"
" EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM ALL_TABLES\n"
" WHERE TABLE_NAME = :1 AND OWNER = UPPER(:2)'\n"
" INTO CNT USING TAB, OWN;\n"
"\n"
" IF CNT = 0 THEN\n"
" EXECUTE IMMEDIATE 'CREATE TABLE %s%s %s';\n"
" SDO_GEOR_UTL.createDMLTrigger( TAB, COL );\n"
" END IF;\n"
"END;",
sTable.c_str(),
sColumn.c_str(),
sOwner.c_str(),
sSchema.c_str(),
sTable.c_str(),
szDescription ) );
if( ! poStmt->Execute() )
{
delete ( poStmt );
return false;
}
delete poStmt;
}
// -----------------------------------------------------------
// Prepare UPDATE or INSERT comand
// -----------------------------------------------------------
CPLString sCommand;
if( bUpdate )
{
sCommand = CPLSPrintf(
"SELECT %s INTO GR1 FROM %s%s T WHERE %s FOR UPDATE;",
sColumn.c_str(),
sSchema.c_str(),
sTable.c_str(),
sWhere.c_str() );
}
else
{
sCommand = CPLSPrintf(
"INSERT INTO %s%s %s RETURNING %s INTO GR1;",
sSchema.c_str(),
sTable.c_str(),
sValues.c_str(),
sColumn.c_str() );
}
// -----------------------------------------------------------
// Create RTD if needed and insert/update GeoRaster
// -----------------------------------------------------------
char szBindRDT[OWNAME];
int nBindRID = 0;
szBindRDT[0] = '\0';
CPLString sObjectTable;
CPLString sSecureFile;
// For version > 11 create RDT as relational table by default,
// if it is not specified by create-option OBJECTTABLE=TRUE
if( poConnection->GetVersion() <= 11 || bCreateObjectTable )
{
sObjectTable = "OF MDSYS.SDO_RASTER\n (";
}
else
{
sObjectTable = CPLSPrintf("(\n"
" RASTERID NUMBER,\n"
" PYRAMIDLEVEL NUMBER,\n"
" BANDBLOCKNUMBER NUMBER,\n"
" ROWBLOCKNUMBER NUMBER,\n"
" COLUMNBLOCKNUMBER NUMBER,\n"
" BLOCKMBR SDO_GEOMETRY,\n"
" RASTERBLOCK BLOB,\n"
" CONSTRAINT '||:rdt||'_RDT_PK ");
}
// For version >= 11 create RDT rasterBlock as securefile
if( poConnection->GetVersion() >= 11 )
{
sSecureFile = "SECUREFILE(CACHE)";
}
else
{
sSecureFile = "(NOCACHE NOLOGGING)";
}
if( poConnection->GetVersion() > 10 )
{
poStmt = poConnection->CreateStatement( CPLSPrintf(
"DECLARE\n"
" TAB VARCHAR2(68) := UPPER('%s');\n"
" COL VARCHAR2(68) := UPPER('%s');\n"
" OWN VARCHAR2(68) := UPPER('%s');\n"
" CNT NUMBER := 0;\n"
" GR1 SDO_GEORASTER := NULL;\n"
"BEGIN\n"
"\n"
" %s\n"
"\n"
" GR1.spatialExtent := NULL;\n"
"\n"
" SELECT GR1.RASTERDATATABLE INTO :rdt FROM DUAL;\n"
" SELECT GR1.RASTERID INTO :rid FROM DUAL;\n"
"\n"
" EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM ALL_OBJECT_TABLES\n"
" WHERE TABLE_NAME = :1 AND OWNER = UPPER(:2)'\n"
" INTO CNT USING :rdt, OWN;\n"
"\n"
" IF CNT = 0 THEN\n"
" EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM ALL_TABLES\n"
" WHERE TABLE_NAME = :1 AND OWNER = UPPER(:2)'\n"
" INTO CNT USING :rdt, OWN;\n"
" END IF;\n"
"\n"
" IF CNT = 0 THEN\n"
" EXECUTE IMMEDIATE 'CREATE TABLE %s'||:rdt||' %s"
"PRIMARY KEY (RASTERID, PYRAMIDLEVEL,\n"
" BANDBLOCKNUMBER, ROWBLOCKNUMBER, COLUMNBLOCKNUMBER))\n"
" LOB(RASTERBLOCK) STORE AS %s';\n"
" END IF;\n"
"\n"
" SDO_GEOR.createTemplate(GR1, %s, null, 'TRUE');\n"
"\n"
" UPDATE %s%s T SET %s = GR1 WHERE\n"
" T.%s.RasterDataTable = :rdt AND\n"
" T.%s.RasterId = :rid;\n"
"\n"
" EXECUTE IMMEDIATE\n"
" 'SELECT T.%s.METADATA.getClobVal()\n"
" FROM %s%s T\n"
" WHERE T.%s.RASTERDATATABLE = UPPER(:1)\n"
" AND T.%s.RASTERID = :2'\n"
" INTO :metadata\n"
" USING :rdt, :rid;\n"
"\n"
" COMMIT;\n"
"\n"
"END;\n",
sTable.c_str(),
sColumn.c_str(),
sOwner.c_str(),
sCommand.c_str(),
sSchema.c_str(),
sObjectTable.c_str(),
sSecureFile.c_str(),
sFormat.c_str(),
sSchema.c_str(),
sTable.c_str(),
sColumn.c_str(),
sColumn.c_str(),
sColumn.c_str(),
sColumn.c_str(),
sSchema.c_str(),
sTable.c_str(),
sColumn.c_str(),
sColumn.c_str() ) );
OCILobLocator* phLocator = NULL;
poStmt->BindName( ":metadata", &phLocator );
poStmt->BindName( ":rdt", szBindRDT );
poStmt->BindName( ":rid", &nBindRID );
CPLErrorReset();
if( ! poStmt->Execute() )
{
delete poStmt;
return false;
}
sDataTable = szBindRDT;
nRasterId = nBindRID;
OCIDescriptorFree( phLocator, OCI_DTYPE_LOB );
delete poStmt;
return true;
}
// -----------------------------------------------------------
// Procedure for Server version older than 11
// -----------------------------------------------------------
char szCreateBlank[OWTEXT];
if( nRasterBands == 1 )
{
strcpy( szCreateBlank, CPLSPrintf( "SDO_GEOR.createBlank(20001, "
"SDO_NUMBER_ARRAY(0, 0), "
"SDO_NUMBER_ARRAY(%d, %d), 0, :rdt, :rid)",
nRasterRows, nRasterColumns ) );
}
else
{
strcpy( szCreateBlank, CPLSPrintf( "SDO_GEOR.createBlank(21001, "
"SDO_NUMBER_ARRAY(0, 0, 0), "
"SDO_NUMBER_ARRAY(%d, %d, %d), 0, :rdt, :rid)",
nRasterRows, nRasterColumns, nRasterBands ) );
}
poStmt = poConnection->CreateStatement( CPLSPrintf(
"DECLARE\n"
" W NUMBER := :1;\n"
" H NUMBER := :2;\n"
" BB NUMBER := :3;\n"
" RB NUMBER := :4;\n"
" CB NUMBER := :5;\n"
" OWN VARCHAR2(68) := UPPER('%s');\n"
" X NUMBER := 0;\n"
" Y NUMBER := 0;\n"
" CNT NUMBER := 0;\n"
" GR1 SDO_GEORASTER := NULL;\n"
" GR2 SDO_GEORASTER := NULL;\n"
" STM VARCHAR2(1024) := '';\n"
"BEGIN\n"
"\n"
" %s\n"
"\n"
" SELECT GR1.RASTERDATATABLE INTO :rdt FROM DUAL;\n"
" SELECT GR1.RASTERID INTO :rid FROM DUAL;\n"
"\n"
" SELECT %s INTO GR2 FROM %s%s T WHERE"
" T.%s.RasterDataTable = :rdt AND"
" T.%s.RasterId = :rid FOR UPDATE;\n"
"\n"
" GR1 := %s;\n"
"\n"
" SDO_GEOR.changeFormatCopy(GR1, '%s', GR2);\n"
"\n"
" UPDATE %s%s T SET %s = GR2 WHERE"
" T.%s.RasterDataTable = :rdt AND"
" T.%s.RasterId = :rid;\n"
"\n"
" EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM ALL_OBJECT_TABLES\n"
" WHERE TABLE_NAME = :1 AND OWNER = UPPER(:2)'\n"
" INTO CNT USING :rdt, OWN;\n"
"\n"
" IF CNT = 0 THEN\n"
" EXECUTE IMMEDIATE 'CREATE TABLE %s'||:rdt||' OF MDSYS.SDO_RASTER\n"
" (PRIMARY KEY (RASTERID, PYRAMIDLEVEL, BANDBLOCKNUMBER,\n"
" ROWBLOCKNUMBER, COLUMNBLOCKNUMBER))\n"
" LOB(RASTERBLOCK) STORE AS (NOCACHE NOLOGGING)';\n"
" ELSE\n"
" EXECUTE IMMEDIATE 'DELETE FROM %s'||:rdt||' WHERE RASTERID ='||:rid||' ';\n"
" END IF;\n"
"\n"
" STM := 'INSERT INTO %s'||:rdt||' VALUES (:1,0,:2-1,:3-1,:4-1,\n"
" SDO_GEOMETRY(2003, NULL, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 3),\n"
" SDO_ORDINATE_ARRAY(:5,:6,:7-1,:8-1)), EMPTY_BLOB() )';\n\n"
" FOR b IN 1..BB LOOP\n"
" Y := 0;\n"
" FOR r IN 1..RB LOOP\n"
" X := 0;\n"
" FOR c IN 1..CB LOOP\n"
" EXECUTE IMMEDIATE STM USING :rid, b, r, c, Y, X, (Y+H), (X+W);\n"
" X := X + W;\n"
" END LOOP;\n"
" Y := Y + H;\n"
" END LOOP;\n"
" END LOOP;\n"
"\n"
" SDO_GEOR.georeference(GR1, %d, %d,"
" SDO_NUMBER_ARRAY(1.0, 0.0, 0.0),"
" SDO_NUMBER_ARRAY(0.0, 1.0, 0.0));\n"
"\n"
" UPDATE %s%s T SET %s = GR1 WHERE"
" T.%s.RasterDataTable = :rdt AND"
" T.%s.RasterId = :rid;\n"
"\n"
" COMMIT;\n"
"\n"
"END;",
sOwner.c_str(),
sCommand.c_str(),
sColumn.c_str(), sSchema.c_str(), sTable.c_str(),
sColumn.c_str(), sColumn.c_str(),
szCreateBlank,
sFormat.c_str(),
sSchema.c_str(), sTable.c_str(),
sColumn.c_str(), sColumn.c_str(), sColumn.c_str(),
sSchema.c_str(), sSchema.c_str(), sSchema.c_str(),
DEFAULT_CRS, MCL_DEFAULT,
sSchema.c_str(), sTable.c_str(),
sColumn.c_str(), sColumn.c_str(), sColumn.c_str() ) );
poStmt->Bind( &nColumnBlockSize );
poStmt->Bind( &nRowBlockSize );
poStmt->Bind( &nTotalBandBlocks );
poStmt->Bind( &nTotalRowBlocks );
poStmt->Bind( &nTotalColumnBlocks );
poStmt->BindName( ":rdt", szBindRDT );
poStmt->BindName( ":rid", &nBindRID );
if( ! poStmt->Execute() )
{
delete poStmt;
return false;
}
sDataTable = szBindRDT;
nRasterId = nBindRID;
delete poStmt;
return true;
}
// ---------------------------------------------------------------------------
// PrepareToOverwrite()
// ---------------------------------------------------------------------------
void GeoRasterWrapper::PrepareToOverwrite( void )
{
nTotalColumnBlocks = 0;
nTotalRowBlocks = 0;
nTotalBandBlocks = 0;
if( sscanf( sCellDepth.c_str(), "%dBIT", &nCellSizeBits ) )
{
nGDALCellBytes = GDALGetDataTypeSize(
OWGetDataType( sCellDepth.c_str() ) ) / 8;
}
else
{
nGDALCellBytes = 1;
}
dfXCoefficient[0] = 1.0;
dfXCoefficient[1] = 0.0;
dfXCoefficient[2] = 0.0;
dfYCoefficient[0] = 0.0;
dfYCoefficient[1] = 1.0;
dfYCoefficient[2] = 0.0;
sCompressionType = "NONE";
nCompressQuality = 75;
bGenPyramid = false;
nPyramidLevels = 0;
sPyramidResampling = "NN";
bIsReferenced = false;
nCacheBlockId = -1;
nCurrentLevel = -1;
pahLevels = NULL;
nLevelOffset = 0L;
sInterleaving = "BSQ";
bUpdate = false;
bInitializeIO = false;
bFlushMetadata = false;
nSRID = 0;
nExtentSRID = 0;
bGenSpatialIndex = false;
bCreateObjectTable = false;
nPyramidMaxLevel = 0;
nBlockCount = 0L;
sDInfo.global_state = 0;
sCInfo.global_state = 0;
bHasBitmapMask = false;
bWriteOnly = false;
bBlocking = true;
bAutoBlocking = false;
eModelCoordLocation = MCL_DEFAULT;
bFlushBlock = false;
nFlushBlockSize = 0L;
phRPC = NULL;
}
// ---------------------------------------------------------------------------
// Delete()
// ---------------------------------------------------------------------------
bool GeoRasterWrapper::Delete( void )
{
if( ! bUniqueFound )
{
return false;
}
OWStatement* poStmt = poConnection->CreateStatement( CPLSPrintf(
"UPDATE %s%s T SET %s = NULL WHERE %s\n",
sSchema.c_str(),
sTable.c_str(),
sColumn.c_str(),
sWhere.c_str() ) );
bool bReturn = poStmt->Execute();
delete poStmt;
return bReturn;
}
// ---------------------------------------------------------------------------
// SetGeoReference()
// ---------------------------------------------------------------------------
void GeoRasterWrapper::SetGeoReference( int nSRIDIn )
{
nSRID = nSRIDIn;
bIsReferenced = true;
bFlushMetadata = true;
}
// ---------------------------------------------------------------------------
// GetRasterInfo()
// ---------------------------------------------------------------------------
void GeoRasterWrapper::GetRasterInfo( void )
{
// -------------------------------------------------------------------
// Get dimensions
// -------------------------------------------------------------------
int nCount = 0;
CPLXMLNode* phDimSize = NULL;
const char* pszType = NULL;
nCount = atoi( CPLGetXMLValue( phMetadata,
"rasterInfo.totalDimensions", "0" ) );
phDimSize = CPLGetXMLNode( phMetadata, "rasterInfo.dimensionSize" );
int i = 0;
for( i = 0; i < nCount; i++ )
{
pszType = CPLGetXMLValue( phDimSize, "type", "0" );
if( EQUAL( pszType, "ROW" ) )
{
nRasterRows = atoi( CPLGetXMLValue( phDimSize, "size", "0" ) );
}
if( EQUAL( pszType, "COLUMN" ) )
{
nRasterColumns = atoi( CPLGetXMLValue( phDimSize, "size", "0" ) );
}
if( EQUAL( pszType, "BAND" ) )
{
nRasterBands = atoi( CPLGetXMLValue( phDimSize, "size", "0" ) );
}
phDimSize = phDimSize->psNext;
}
if( nRasterBands == 0 )
{
nRasterBands = 1;
}
// -------------------------------------------------------------------
// Load NoData Values
// -------------------------------------------------------------------
LoadNoDataValues();
// -------------------------------------------------------------------
// Get ULTCoordinate values
// -------------------------------------------------------------------
anULTCoordinate[0] = atoi(CPLGetXMLValue(
phMetadata, "rasterInfo.ULTCoordinate.column", "0"));
anULTCoordinate[1] = atoi(CPLGetXMLValue(
phMetadata, "rasterInfo.ULTCoordinate.row", "0"));
anULTCoordinate[2] = atoi(CPLGetXMLValue(
phMetadata, "rasterInfo.ULTCoordinate.band", "0"));
// -------------------------------------------------------------------
// Get Interleaving mode
// -------------------------------------------------------------------
sInterleaving = CPLGetXMLValue( phMetadata,
"rasterInfo.interleaving", "BSQ" );
// -------------------------------------------------------------------
// Get blocking
// -------------------------------------------------------------------
nRowBlockSize = atoi( CPLGetXMLValue( phMetadata,
"rasterInfo.blocking.rowBlockSize",
CPLSPrintf( "%d", nRasterRows ) ) );
nColumnBlockSize = atoi( CPLGetXMLValue( phMetadata,
"rasterInfo.blocking.columnBlockSize",
CPLSPrintf( "%d", nRasterColumns ) ) );
nBandBlockSize = atoi( CPLGetXMLValue( phMetadata,
"rasterInfo.blocking.bandBlockSize",
CPLSPrintf( "%d", nRasterBands ) ) );
nTotalColumnBlocks = atoi( CPLGetXMLValue( phMetadata,
"rasterInfo.blocking.totalColumnBlocks","1") );
nTotalRowBlocks = atoi( CPLGetXMLValue( phMetadata,
"rasterInfo.blocking.totalRowBlocks", "1" ) );
nTotalBandBlocks = atoi( CPLGetXMLValue( phMetadata,
"rasterInfo.blocking.totalBandBlocks", "1" ) );
if( nBandBlockSize == -1 )
{
nBandBlockSize = nRasterBands;
}
// -------------------------------------------------------------------
// Get data type
// -------------------------------------------------------------------
sCellDepth = CPLGetXMLValue( phMetadata, "rasterInfo.cellDepth", "8BIT_U" );
if( sscanf( sCellDepth.c_str(), "%dBIT", &nCellSizeBits ) )
{
nGDALCellBytes = GDALGetDataTypeSize(
OWGetDataType( sCellDepth.c_str() ) ) / 8;
}
else
{
nGDALCellBytes = 1;
}
sCompressionType = CPLGetXMLValue( phMetadata,
"rasterInfo.compression.type", "NONE" );
if( EQUALN( sCompressionType.c_str(), "JPEG", 4 ) )
{
nCompressQuality = atoi( CPLGetXMLValue( phMetadata,
"rasterInfo.compression.quality", "75" ) );
}
if( EQUALN( sCompressionType.c_str(), "JPEG", 4 ) )
{
sInterleaving = "BIP";
}
// -------------------------------------------------------------------
// Get default RGB Bands
// -------------------------------------------------------------------
iDefaultRedBand = atoi( CPLGetXMLValue( phMetadata,
"objectInfo.defaultRed", "-1" ) );
iDefaultGreenBand = atoi( CPLGetXMLValue( phMetadata,
"objectInfo.defaultGreen", "-1" ) );
iDefaultBlueBand = atoi( CPLGetXMLValue( phMetadata,
"objectInfo.defaultBlue", "-1" ) );
// -------------------------------------------------------------------
// Get Pyramid details
// -------------------------------------------------------------------
char szPyramidType[OWCODE];
strcpy( szPyramidType, CPLGetXMLValue( phMetadata,
"rasterInfo.pyramid.type", "None" ) );
if( EQUAL( szPyramidType, "DECREASE" ) )
{
nPyramidMaxLevel = atoi( CPLGetXMLValue( phMetadata,
"rasterInfo.pyramid.maxLevel", "0" ) );
}
// -------------------------------------------------------------------
// Check for RPCs
// -------------------------------------------------------------------
const char* pszModelType = CPLGetXMLValue( phMetadata,
"spatialReferenceInfo.modelType", "None" );
if( EQUAL( pszModelType, "FunctionalFitting" ) )
{
GetRPC();
}
// -------------------------------------------------------------------
// Prepare to get Extents
// -------------------------------------------------------------------
bIsReferenced = EQUAL( "TRUE", CPLGetXMLValue( phMetadata,
"spatialReferenceInfo.isReferenced", "FALSE" ) );
nSRID = atoi( CPLGetXMLValue( phMetadata,
"spatialReferenceInfo.SRID", "0" ) );
}
// ---------------------------------------------------------------------------
// GetStatistics()
// ---------------------------------------------------------------------------
bool GeoRasterWrapper::GetStatistics( int nBand,
char* pszMin,
char* pszMax,
char* pszMean,
char* pszMedian,
char* pszMode,
char* pszStdDev,
char* pszSampling )
{
int n = 1;
CPLXMLNode *phSubLayer = CPLGetXMLNode( phMetadata, "layerInfo.subLayer" );
for( n = 1 ; phSubLayer ; phSubLayer = phSubLayer->psNext, n++ )
{
if( n == nBand && CPLGetXMLNode( phSubLayer, "statisticDataset" ) )
{
strncpy( pszSampling, CPLGetXMLValue( phSubLayer,
"statisticDataset.samplingFactor", "0.0" ), MAX_DOUBLE_STR_REP );
strncpy( pszMin, CPLGetXMLValue( phSubLayer,
"statisticDataset.MIN", "0.0" ), MAX_DOUBLE_STR_REP );
strncpy( pszMax, CPLGetXMLValue( phSubLayer,
"statisticDataset.MAX", "0.0" ), MAX_DOUBLE_STR_REP );
strncpy( pszMean, CPLGetXMLValue( phSubLayer,
"statisticDataset.MEAN", "0.0" ), MAX_DOUBLE_STR_REP );
strncpy( pszMedian, CPLGetXMLValue( phSubLayer,
"statisticDataset.MEDIAN", "0.0" ), MAX_DOUBLE_STR_REP );
strncpy( pszMode, CPLGetXMLValue( phSubLayer,
"statisticDataset.MODEVALUE", "0.0" ), MAX_DOUBLE_STR_REP );
strncpy( pszStdDev, CPLGetXMLValue( phSubLayer,
"statisticDataset.STD", "0.0" ), MAX_DOUBLE_STR_REP );
return true;
}
}
return false;
}
// ---------------------------------------------------------------------------
// SetStatistics()
// ---------------------------------------------------------------------------
bool GeoRasterWrapper::SetStatistics( int nBand,
const char* pszMin,
const char* pszMax,
const char* pszMean,
const char* pszMedian,
const char* pszMode,
const char* pszStdDev,
const char* pszSampling )
{
InitializeLayersNode();
bFlushMetadata = true;
int n = 1;
CPLXMLNode* phSubLayer = CPLGetXMLNode( phMetadata, "layerInfo.subLayer" );
for( n = 1 ; phSubLayer ; phSubLayer = phSubLayer->psNext, n++ )
{
if( n != nBand )
{
continue;
}
CPLXMLNode* psSDaset = CPLGetXMLNode( phSubLayer, "statisticDataset" );
if( psSDaset != NULL )
{
CPLRemoveXMLChild( phSubLayer, psSDaset );
CPLDestroyXMLNode( psSDaset );
}
psSDaset = CPLCreateXMLNode(phSubLayer,CXT_Element,"statisticDataset");
CPLCreateXMLElementAndValue(psSDaset,"samplingFactor", pszSampling );
CPLCreateXMLElementAndValue(psSDaset,"MIN", pszMin );
CPLCreateXMLElementAndValue(psSDaset,"MAX", pszMax );
CPLCreateXMLElementAndValue(psSDaset,"MEAN", pszMean );
CPLCreateXMLElementAndValue(psSDaset,"MEDIAN", pszMedian );
CPLCreateXMLElementAndValue(psSDaset,"MODEVALUE", pszMode );
CPLCreateXMLElementAndValue(psSDaset,"STD", pszStdDev );
return true;
}
return false;
}
// ---------------------------------------------------------------------------
// HasColorTable()
// ---------------------------------------------------------------------------
bool GeoRasterWrapper::HasColorMap( int nBand )
{
CPLXMLNode *psLayers;
int n = 1;
psLayers = CPLGetXMLNode( phMetadata, "layerInfo.subLayer" );
for( ; psLayers; psLayers = psLayers->psNext, n++ )
{
if( n == nBand )
{
if( CPLGetXMLNode( psLayers, "colorMap.colors" ) )
{
return true;
}
}
}
return false;
}
// ---------------------------------------------------------------------------
// InitializeLayersNode()
// ---------------------------------------------------------------------------
void GeoRasterWrapper::InitializeLayersNode()
{
CPLXMLNode *pslInfo = CPLGetXMLNode( phMetadata, "layerInfo" );
int n = 1;
for( n = 0 ; n < nRasterBands; n++ )
{
CPLXMLNode *psSLayer = CPLGetXMLNode( pslInfo, "subLayer" );
if( psSLayer == NULL )
{
psSLayer = CPLCreateXMLNode( pslInfo, CXT_Element, "subLayer" );
CPLCreateXMLElementAndValue( psSLayer, "layerNumber",
CPLSPrintf( "%d", n + 1 ) );
CPLCreateXMLElementAndValue( psSLayer, "layerDimensionOrdinate",
CPLSPrintf( "%d", n ) );
CPLCreateXMLElementAndValue( psSLayer, "layerID", "" );
}
}
}
// ---------------------------------------------------------------------------
// GetColorTable()
// ---------------------------------------------------------------------------
void GeoRasterWrapper::GetColorMap( int nBand, GDALColorTable* poCT )
{
GDALColorEntry oEntry;
CPLXMLNode* psLayers;
int n = 1;
psLayers = CPLGetXMLNode( phMetadata, "layerInfo.subLayer" );
for( ; psLayers; psLayers = psLayers->psNext, n++ )
{
if( n != nBand )
{
continue;
}
CPLXMLNode* psColors = CPLGetXMLNode( psLayers, "colorMap.colors.cell" );
int iColor = 0;
for( ; psColors; psColors = psColors->psNext )
{
iColor = (short) atoi( CPLGetXMLValue( psColors, "value","0"));
oEntry.c1 = (short) atoi( CPLGetXMLValue( psColors, "red", "0"));
oEntry.c2 = (short) atoi( CPLGetXMLValue( psColors, "green","0"));
oEntry.c3 = (short) atoi( CPLGetXMLValue( psColors, "blue", "0"));
oEntry.c4 = (short) atoi( CPLGetXMLValue( psColors, "alpha","0"));
poCT->SetColorEntry( iColor, &oEntry );
}
break;
}
}
// ---------------------------------------------------------------------------
// SetColorTable()
// ---------------------------------------------------------------------------
void GeoRasterWrapper::SetColorMap( int nBand, GDALColorTable* poCT )
{
InitializeLayersNode();
bFlushMetadata = true;
GDALColorEntry oEntry;
int n = 1;
CPLXMLNode* phSubLayer = CPLGetXMLNode( phMetadata, "layerInfo.subLayer" );
for( n = 1 ; phSubLayer ; phSubLayer = phSubLayer->psNext, n++ )
{
if( n != nBand )
{
continue;
}
CPLXMLNode* psCMap = CPLGetXMLNode( phSubLayer, "colorMap" );
if( psCMap != NULL )
{
CPLRemoveXMLChild( phSubLayer, psCMap );
CPLDestroyXMLNode( psCMap );
}
psCMap = CPLCreateXMLNode( phSubLayer, CXT_Element, "colorMap" );
CPLXMLNode* psColor = CPLCreateXMLNode( psCMap, CXT_Element, "colors" );
// ------------------------------------------------
// Clean existing colors entry (RGB color table)
// ------------------------------------------------
if( psColor != NULL )
{
CPLRemoveXMLChild( psCMap, psColor );
CPLDestroyXMLNode( psColor );
}
psColor = CPLCreateXMLNode( psCMap, CXT_Element, "colors" );
int iColor = 0;
int nCount = 0;
switch( nCellSizeBits )
{
case 1 :
nCount = 2;
break;
case 2 :
nCount = 4;
break;
case 4:
nCount = 16;
break;
default:
nCount = poCT->GetColorEntryCount();
}
for( iColor = 0; iColor < nCount; iColor++ )
{
poCT->GetColorEntryAsRGB( iColor, &oEntry );
CPLXMLNode* psCell = CPLCreateXMLNode( psColor, CXT_Element, "cell" );
CPLSetXMLValue( psCell, "#value", CPLSPrintf("%d", iColor) );
CPLSetXMLValue( psCell, "#blue", CPLSPrintf("%d", oEntry.c3) );
CPLSetXMLValue( psCell, "#red", CPLSPrintf("%d", oEntry.c1) );
CPLSetXMLValue( psCell, "#green", CPLSPrintf("%d", oEntry.c2) );
CPLSetXMLValue( psCell, "#alpha", CPLSPrintf("%d", oEntry.c4) );
}
}
}
// ---------------------------------------------------------------------------
// InitializeIO()
// ---------------------------------------------------------------------------
bool GeoRasterWrapper::InitializeIO( void )
{
bInitializeIO = true;
// --------------------------------------------------------------------
// Initialize Pyramid level details
// --------------------------------------------------------------------
pahLevels = (hLevelDetails*) CPLCalloc( sizeof(hLevelDetails),
nPyramidMaxLevel + 1 );
// --------------------------------------------------------------------
// Calculate number and size of the blocks in level zero
// --------------------------------------------------------------------
nBlockCount = (unsigned long) ( nTotalColumnBlocks * nTotalRowBlocks * nTotalBandBlocks );
nBlockBytes = (unsigned long) ( nColumnBlockSize * nRowBlockSize * nBandBlockSize *
nCellSizeBits / 8L );
nGDALBlockBytes = (unsigned long) ( nColumnBlockSize * nRowBlockSize * nGDALCellBytes );
pahLevels[0].nColumnBlockSize = nColumnBlockSize;
pahLevels[0].nRowBlockSize = nRowBlockSize;
pahLevels[0].nTotalColumnBlocks = nTotalColumnBlocks;
pahLevels[0].nTotalRowBlocks = nTotalRowBlocks;
pahLevels[0].nBlockCount = nBlockCount;
pahLevels[0].nBlockBytes = nBlockBytes;
pahLevels[0].nGDALBlockBytes = nGDALBlockBytes;
pahLevels[0].nOffset = 0L;
// --------------------------------------------------------------------
// Calculate number and size of the blocks in Pyramid levels
// --------------------------------------------------------------------
int iLevel = 1;
for( iLevel = 1; iLevel <= nPyramidMaxLevel; iLevel++ )
{
int nRBS = nRowBlockSize;
int nCBS = nColumnBlockSize;
int nTCB = nTotalColumnBlocks;
int nTRB = nTotalRowBlocks;
// --------------------------------------------------------------------
// Calculate the actual size of a lower resolution block
// --------------------------------------------------------------------
double dfScale = pow( (double) 2.0, (double) iLevel );
int nXSize = (int) floor( (double) nRasterColumns / dfScale );
int nYSize = (int) floor( (double) nRasterRows / dfScale );
int nXBlock = (int) floor( (double) nCBS / 2.0 );
int nYBlock = (int) floor( (double) nRBS / 2.0 );
if( nXSize <= nXBlock && nYSize <= nYBlock )
{
// ------------------------------------------------------------
// Calculate the size of the singe small blocks
// ------------------------------------------------------------
nCBS = nXSize;
nRBS = nYSize;
nTCB = 1;
nTRB = 1;
}
else
{
// ------------------------------------------------------------
// Recalculate blocks quantity
// ------------------------------------------------------------
nTCB = (int) ceil( (double) nXSize / nCBS );
nTRB = (int) ceil( (double) nYSize / nRBS );
}
// --------------------------------------------------------------------
// Save level datails
// --------------------------------------------------------------------
pahLevels[iLevel].nColumnBlockSize = nCBS;
pahLevels[iLevel].nRowBlockSize = nRBS;
pahLevels[iLevel].nTotalColumnBlocks = nTCB;
pahLevels[iLevel].nTotalRowBlocks = nTRB;
pahLevels[iLevel].nBlockCount = (unsigned long ) ( nTCB * nTRB * nTotalBandBlocks );
pahLevels[iLevel].nBlockBytes = (unsigned long ) ( nCBS * nRBS * nBandBlockSize *
nCellSizeBits / 8L );
pahLevels[iLevel].nGDALBlockBytes = (unsigned long ) ( nCBS * nRBS * nGDALCellBytes );
pahLevels[iLevel].nOffset = 0L;
}
// --------------------------------------------------------------------
// Calculate total row count and level's offsets
// --------------------------------------------------------------------
nBlockCount = 0L;
for( iLevel = 0; iLevel <= nPyramidMaxLevel; iLevel++ )
{
pahLevels[iLevel].nOffset = nBlockCount;
nBlockCount += pahLevels[iLevel].nBlockCount;
}
// --------------------------------------------------------------------
// Allocate buffer for one raster block
// --------------------------------------------------------------------
long nMaxBufferSize = MAX( nBlockBytes, nGDALBlockBytes );
pabyBlockBuf = (GByte*) VSIMalloc( sizeof(GByte) * nMaxBufferSize );
if ( pabyBlockBuf == NULL )
{
CPLError( CE_Failure, CPLE_OutOfMemory,
"InitializeIO - Block Buffer error\n"
"Cannot allocate memory buffer of (%ld) bytes "
"Consider the use of *smaller* block size",
nMaxBufferSize );
return false;
}
// --------------------------------------------------------------------
// Allocate buffer for one compressed raster block
// --------------------------------------------------------------------
if( bUpdate && ! EQUAL( sCompressionType.c_str(), "NONE") )
{
pabyCompressBuf = (GByte*) VSIMalloc( sizeof(GByte) * nMaxBufferSize );
if ( pabyCompressBuf == NULL )
{
CPLError( CE_Failure, CPLE_OutOfMemory,
"InitializeIO - Compression Buffer error\n"
"Cannot allocate memory buffer of (%ld) bytes "
"Consider the use of *smaller* block size",
nMaxBufferSize );
return false;
}
}
// --------------------------------------------------------------------
// Allocate array of LOB Locators
// --------------------------------------------------------------------
pahLocator = (OCILobLocator**) VSIMalloc( sizeof(void*) * nBlockCount );
if ( pahLocator == NULL )
{
CPLError( CE_Failure, CPLE_OutOfMemory,
"InitializeIO - LobLocator Array error\n"
"Cannot allocate memory buffer of (%ld) bytes "
"Consider the use of *bigger* block size",
(sizeof(void*) * nBlockCount) );
return false;
}
// --------------------------------------------------------------------
// Issue a statement to load the locators
// --------------------------------------------------------------------
const char* pszUpdate = "";
if( bUpdate )
{
pszUpdate = CPLStrdup( "\nFOR UPDATE" );
}
poBlockStmt = poConnection->CreateStatement( CPLSPrintf(
"SELECT RASTERBLOCK\n"
"FROM %s%s\n"
"WHERE RASTERID = :1\n"
"ORDER BY\n"
" PYRAMIDLEVEL ASC,\n"
" BANDBLOCKNUMBER ASC,\n"
" ROWBLOCKNUMBER ASC,\n"
" COLUMNBLOCKNUMBER ASC%s",
sSchema.c_str(),
sDataTable.c_str(),
pszUpdate ) );
poBlockStmt->Bind( &nRasterId );
poBlockStmt->Define( pahLocator, nBlockCount );
if( ! poBlockStmt->Execute( nBlockCount ) )
{
return false;
}
return true;
}
// ---------------------------------------------------------------------------
// InitializeLevel()
// ---------------------------------------------------------------------------
void GeoRasterWrapper::InitializeLevel( int nLevel )
{
nCurrentLevel = nLevel;
nColumnBlockSize = pahLevels[nLevel].nColumnBlockSize;
nRowBlockSize = pahLevels[nLevel].nRowBlockSize;
nTotalColumnBlocks = pahLevels[nLevel].nTotalColumnBlocks;
nTotalRowBlocks = pahLevels[nLevel].nTotalRowBlocks;
nBlockBytes = pahLevels[nLevel].nBlockBytes;
nGDALBlockBytes = pahLevels[nLevel].nGDALBlockBytes;
nLevelOffset = pahLevels[nLevel].nOffset;
}
// ---------------------------------------------------------------------------
// GetDataBlock()
// ---------------------------------------------------------------------------
bool GeoRasterWrapper::GetDataBlock( int nBand,
int nLevel,
int nXOffset,
int nYOffset,
void* pData )
{
if( ! bInitializeIO )
{
if( InitializeIO() == false )
{
return false;
}
}
if( nCurrentLevel != nLevel )
{
InitializeLevel( nLevel );
}
long nBlock = GetBlockNumber( nBand, nXOffset, nYOffset );
CPLDebug( "Read ",
"Block = %4ld Size = %7ld Band = %d Level = %d X = %d Y = %d",
nBlock, nBlockBytes, nBand, nLevel, nXOffset, nYOffset );
if( nCacheBlockId != nBlock )
{
if ( bFlushBlock )
{
if( ! FlushBlock( nCacheBlockId ) )
{
return false;
}
}
nCacheBlockId = nBlock;
unsigned long nBytesRead = 0;
nBytesRead = poBlockStmt->ReadBlob( pahLocator[nBlock],
pabyBlockBuf,
nBlockBytes );
CPLDebug( "Load ", "Block = %4ld Size = %7ld", nBlock, nBlockBytes );
if( nBytesRead == 0 )
{
memset( pData, 0, nGDALBlockBytes );
return true;
}
if( nBytesRead < nBlockBytes &&
EQUAL( sCompressionType.c_str(), "NONE") )
{
CPLError( CE_Warning, CPLE_AppDefined,
"BLOB size (%ld) is smaller than expected (%ld) !",
nBytesRead, nBlockBytes );
memset( pData, 0, nGDALBlockBytes );
return true;
}
if( nBytesRead > nBlockBytes )
{
CPLError( CE_Warning, CPLE_AppDefined,
"BLOB size (%ld) is bigger than expected (%ld) !",
nBytesRead, nBlockBytes );
memset( pData, 0, nGDALBlockBytes );
return true;
}
#ifndef CPL_MSB
if( nCellSizeBits > 8 )
{
int nWordSize = nCellSizeBits / 8;
int nWordCount = nColumnBlockSize * nRowBlockSize * nBandBlockSize;
GDALSwapWords( pabyBlockBuf, nWordSize, nWordCount, nWordSize );
}
#endif
// ----------------------------------------------------------------
// Uncompress
// ----------------------------------------------------------------
if( EQUALN( sCompressionType.c_str(), "JPEG", 4 ) )
{
UncompressJpeg( nBytesRead );
}
else if ( EQUAL( sCompressionType.c_str(), "DEFLATE" ) )
{
UncompressDeflate( nBytesRead );
}
// ----------------------------------------------------------------
// Unpack NBits
// ----------------------------------------------------------------
if( nCellSizeBits < 8 || nLevel == DEFAULT_BMP_MASK )
{
UnpackNBits( pabyBlockBuf );
}
}
// --------------------------------------------------------------------
// Uninterleaving, extract band from block buffer
// --------------------------------------------------------------------
int nStart = ( nBand - 1 ) % nBandBlockSize;
if( EQUAL( sInterleaving.c_str(), "BSQ" ) || nBandBlockSize == 1 )
{
nStart *= nGDALBlockBytes;
memcpy( pData, &pabyBlockBuf[nStart], nGDALBlockBytes );
}
else
{
int nIncr = nBandBlockSize * nGDALCellBytes;
int nSize = nGDALCellBytes;
if( EQUAL( sInterleaving.c_str(), "BIL" ) )
{
nStart *= nColumnBlockSize;
nIncr *= nColumnBlockSize;
nSize *= nColumnBlockSize;
}
GByte* pabyData = (GByte*) pData;
unsigned long ii = 0;
unsigned long jj = nStart * nGDALCellBytes;
for( ii = 0; ii < nGDALBlockBytes; ii += nSize, jj += nIncr )
{
memcpy( &pabyData[ii], &pabyBlockBuf[jj], nSize );
}
}
return true;
}
// ---------------------------------------------------------------------------
// SetDataBlock()
// ---------------------------------------------------------------------------
bool GeoRasterWrapper::SetDataBlock( int nBand,
int nLevel,
int nXOffset,
int nYOffset,
void* pData )
{
#ifndef CPL_MSB
if( nCellSizeBits > 8 )
{
int nWordSize = nCellSizeBits / 8;
int nWordCount = nColumnBlockSize * nRowBlockSize;
GDALSwapWords( pData, nWordSize, nWordCount, nWordSize );
}
#endif
if( ! bInitializeIO )
{
if( InitializeIO() == false )
{
return false;
}
}
if( nCurrentLevel != nLevel )
{
InitializeLevel( nLevel );
}
long nBlock = GetBlockNumber( nBand, nXOffset, nYOffset );
CPLDebug( "Write ",
"Block = %4ld Size = %7ld Band = %d Level = %d X = %d Y = %d",
nBlock, nBlockBytes, nBand, nLevel, nXOffset, nYOffset );
// --------------------------------------------------------------------
// Flush previous block
// --------------------------------------------------------------------
if( nCacheBlockId != nBlock && bFlushBlock )
{
if( ! FlushBlock( nCacheBlockId ) )
{
return false;
}
}
// --------------------------------------------------------------------
// Re-load interleaved block
// --------------------------------------------------------------------
if( nBandBlockSize > 1 && bWriteOnly == false && nCacheBlockId != nBlock )
{
nCacheBlockId = nBlock;
unsigned long nBytesRead = 0;
nBytesRead = poBlockStmt->ReadBlob( pahLocator[nBlock],
pabyBlockBuf,
nBlockBytes );
CPLDebug( "Reload", "Block = %4ld Size = %7ld", nBlock, nBlockBytes );
if( nBytesRead == 0 )
{
memset( pabyBlockBuf, 0, nBlockBytes );
}
else
{
// ------------------------------------------------------------
// Uncompress
// ------------------------------------------------------------
if( EQUALN( sCompressionType.c_str(), "JPEG", 4 ) )
{
UncompressJpeg( nBytesRead );
}
else if ( EQUAL( sCompressionType.c_str(), "DEFLATE" ) )
{
UncompressDeflate( nBytesRead );
}
// ------------------------------------------------------------
// Unpack NBits
// ------------------------------------------------------------
if( nCellSizeBits < 8 || nLevel == DEFAULT_BMP_MASK )
{
UnpackNBits( pabyBlockBuf );
}
}
}
GByte *pabyInBuf = (GByte *) pData;
// --------------------------------------------------------------------
// Interleave
// --------------------------------------------------------------------
int nStart = ( nBand - 1 ) % nBandBlockSize;
if( EQUAL( sInterleaving.c_str(), "BSQ" ) || nBandBlockSize == 1 )
{
nStart *= nGDALBlockBytes;
memcpy( &pabyBlockBuf[nStart], pabyInBuf, nGDALBlockBytes );
}
else
{
int nIncr = nBandBlockSize * nGDALCellBytes;
int nSize = nGDALCellBytes;
if( EQUAL( sInterleaving.c_str(), "BIL" ) )
{
nStart *= nColumnBlockSize;
nIncr *= nColumnBlockSize;
nSize *= nColumnBlockSize;
}
unsigned long ii = 0;
unsigned long jj = nStart * nGDALCellBytes;
for( ii = 0; ii < nGDALBlockBytes; ii += nSize, jj += nIncr )
{
memcpy( &pabyBlockBuf[jj], &pabyInBuf[ii], nSize );
}
}
// --------------------------------------------------------------------
// Flag the flush block
// --------------------------------------------------------------------
nCacheBlockId = nBlock;
bFlushBlock = true;
nFlushBlockSize = nBlockBytes;
return true;
}
// ---------------------------------------------------------------------------
// FlushBlock()
// ---------------------------------------------------------------------------
bool GeoRasterWrapper::FlushBlock( long nCacheBlock )
{
GByte* pabyFlushBuffer = (GByte *) pabyBlockBuf;
// --------------------------------------------------------------------
// Pack bits ( inside pabyOutBuf )
// --------------------------------------------------------------------
if( nCellSizeBits < 8 || nCurrentLevel == DEFAULT_BMP_MASK )
{
PackNBits( pabyFlushBuffer );
}
// --------------------------------------------------------------------
// Compress ( from pabyBlockBuf to pabyBlockBuf2 )
// --------------------------------------------------------------------
if( ! EQUAL( sCompressionType.c_str(), "NONE" ) )
{
if( EQUALN( sCompressionType.c_str(), "JPEG", 4 ) )
{
nFlushBlockSize = CompressJpeg();
}
else if ( EQUAL( sCompressionType.c_str(), "DEFLATE" ) )
{
nFlushBlockSize = CompressDeflate();
}
pabyFlushBuffer = pabyCompressBuf;
}
// --------------------------------------------------------------------
// Write BLOB
// --------------------------------------------------------------------
CPLDebug( "Flush ", "Block = %4ld Size = %7ld", nCacheBlock,
nFlushBlockSize );
if( ! poBlockStmt->WriteBlob( pahLocator[nCacheBlock],
pabyFlushBuffer,
nFlushBlockSize ) )
{
return false;
}
bFlushBlock = false;
bFlushMetadata = true;
nFlushBlockSize = nBlockBytes;
return true;
}
// ---------------------------------------------------------------------------
// LoadNoDataValues()
// ---------------------------------------------------------------------------
CPLList* AddToNoDataList( CPLXMLNode* phNode, int nNumber, CPLList* poList )
{
CPLXMLNode* psChild = phNode->psChild;
const char* pszMin = NULL;
const char* pszMax = NULL;
for( ; psChild ; psChild = psChild->psNext )
{
if( EQUAL( psChild->pszValue, "value" ) )
{
pszMin = CPLGetXMLValue( psChild, NULL, "NONE" );
pszMax = pszMin;
}
else if ( EQUAL( psChild->pszValue, "range" ) )
{
pszMin = CPLGetXMLValue( psChild, "min", "NONE" );
pszMax = CPLGetXMLValue( psChild, "max", "NONE" );
}
else
{
continue;
}
hNoDataItem* poItem = (hNoDataItem*) CPLMalloc( sizeof( hNoDataItem ) );
poItem->nBand = nNumber;
poItem->dfLower = CPLAtof( pszMin );
poItem->dfUpper = CPLAtof( pszMax );
poList = CPLListAppend( poList, poItem );
}
return poList;
}
void GeoRasterWrapper::LoadNoDataValues( void )
{
CPLListDestroy( psNoDataList );
CPLXMLNode* phLayerInfo = CPLGetXMLNode( phMetadata, "layerInfo" );
if( phLayerInfo == NULL )
{
return;
}
// -------------------------------------------------------------------
// Load NoDatas from list of values and list of value ranges
// -------------------------------------------------------------------
CPLXMLNode* phObjNoData = CPLGetXMLNode( phLayerInfo, "objectLayer.NODATA" );
for( ; phObjNoData ; phObjNoData = phObjNoData->psNext )
{
psNoDataList = AddToNoDataList( phObjNoData, 0, psNoDataList );
}
CPLXMLNode* phSubLayer = CPLGetXMLNode( phLayerInfo, "subLayer" );
for( ; phSubLayer ; phSubLayer = phSubLayer->psNext )
{
int nNumber = atoi( CPLGetXMLValue( phSubLayer, "layerNumber", "-1") );
CPLXMLNode* phSubNoData = CPLGetXMLNode( phSubLayer, "NODATA" );
if( phSubNoData )
{
psNoDataList = AddToNoDataList( phSubNoData, nNumber, psNoDataList );
}
}
}
// ---------------------------------------------------------------------------
// GetRPC()
// ---------------------------------------------------------------------------
/* This is the order for storing 20 coeffients in GeoRaster Metadata */
static const int anOrder[] = {
1, 2, 8, 12, 3, 5, 15, 9, 13, 16, 4, 6, 18, 7, 11, 19, 10, 14, 17, 20
};
void GeoRasterWrapper::GetRPC()
{
int i;
CPLXMLNode* phSRSInfo = CPLGetXMLNode( phMetadata,
"spatialReferenceInfo" );
if( phSRSInfo == NULL )
{
return;
}
const char* pszModelType = CPLGetXMLValue( phMetadata,
"spatialReferenceInfo.modelType", "None" );
if( EQUAL( pszModelType, "FunctionalFitting" ) == false )
{
return;
}
CPLXMLNode* phPolyModel = CPLGetXMLNode( phSRSInfo, "polynomialModel" );
if ( phPolyModel == NULL )
{
return;
}
// pPolynomial refers to LINE_NUM
CPLXMLNode* phPolynomial = CPLGetXMLNode( phPolyModel, "pPolynomial" );
if ( phPolynomial == NULL )
{
return;
}
int nNumCoeff = atoi( CPLGetXMLValue( phPolynomial, "nCoefficients", "0" ) );
if ( nNumCoeff != 20 )
{
return;
}
const char* pszPolyCoeff = CPLGetXMLValue( phPolynomial, "polynomialCoefficients", "None" );
if ( EQUAL( pszPolyCoeff, "None" ) )
{
return;
}
char** papszCeoff = CSLTokenizeString2( pszPolyCoeff, " ", CSLT_STRIPLEADSPACES );
if( CSLCount( papszCeoff ) != 20 )
{
return;
}
phRPC = (GDALRPCInfo*) VSIMalloc( sizeof(GDALRPCInfo) );
phRPC->dfLINE_OFF = CPLAtof( CPLGetXMLValue( phPolyModel, "rowOff", "0" ) );
phRPC->dfSAMP_OFF = CPLAtof( CPLGetXMLValue( phPolyModel, "columnOff", "0" ) );
phRPC->dfLONG_OFF = CPLAtof( CPLGetXMLValue( phPolyModel, "xOff", "0" ) );
phRPC->dfLAT_OFF = CPLAtof( CPLGetXMLValue( phPolyModel, "yOff", "0" ) );
phRPC->dfHEIGHT_OFF = CPLAtof( CPLGetXMLValue( phPolyModel, "zOff", "0" ) );
phRPC->dfLINE_SCALE = CPLAtof( CPLGetXMLValue( phPolyModel, "rowScale", "0" ) );
phRPC->dfSAMP_SCALE = CPLAtof( CPLGetXMLValue( phPolyModel, "columnScale", "0" ) );
phRPC->dfLONG_SCALE = CPLAtof( CPLGetXMLValue( phPolyModel, "xScale", "0" ) );
phRPC->dfLAT_SCALE = CPLAtof( CPLGetXMLValue( phPolyModel, "yScale", "0" ) );
phRPC->dfHEIGHT_SCALE = CPLAtof( CPLGetXMLValue( phPolyModel, "zScale", "0" ) );
for( i = 0; i < 20; i++ )
{
phRPC->adfLINE_NUM_COEFF[anOrder[i] - 1] = CPLAtof( papszCeoff[i] );
}
// qPolynomial refers to LINE_DEN
phPolynomial = CPLGetXMLNode( phPolyModel, "qPolynomial" );
if ( phPolynomial == NULL )
{
CPLFree( phRPC );
phRPC = NULL;
return;
}
pszPolyCoeff = CPLGetXMLValue( phPolynomial, "polynomialCoefficients", "None" );
if ( EQUAL( pszPolyCoeff, "None" ) )
{
CPLFree( phRPC );
phRPC = NULL;
return;
}
papszCeoff = CSLTokenizeString2( pszPolyCoeff, " ", CSLT_STRIPLEADSPACES );
if( CSLCount( papszCeoff ) != 20 )
{
CPLFree( phRPC );
phRPC = NULL;
return;
}
for( i = 0; i < 20; i++ )
{
phRPC->adfLINE_DEN_COEFF[anOrder[i] - 1] = CPLAtof( papszCeoff[i] );
}
// rPolynomial refers to SAMP_NUM
phPolynomial = CPLGetXMLNode( phPolyModel, "rPolynomial" );
if ( phPolynomial == NULL )
{
CPLFree( phRPC );
phRPC = NULL;
return;
}
pszPolyCoeff = CPLGetXMLValue( phPolynomial, "polynomialCoefficients", "None" );
if ( EQUAL( pszPolyCoeff, "None" ) )
{
CPLFree( phRPC );
phRPC = NULL;
return;
}
papszCeoff = CSLTokenizeString2( pszPolyCoeff, " ", CSLT_STRIPLEADSPACES );
if( CSLCount( papszCeoff ) != 20 )
{
CPLFree( phRPC );
phRPC = NULL;
return;
}
for( i = 0; i < 20; i++ )
{
phRPC->adfSAMP_NUM_COEFF[anOrder[i] - 1] = CPLAtof( papszCeoff[i] );
}
// sPolynomial refers to SAMP_DEN
phPolynomial = CPLGetXMLNode( phPolyModel, "sPolynomial" );
if ( phPolynomial == NULL )
{
CPLFree( phRPC );
phRPC = NULL;
return;
}
pszPolyCoeff = CPLGetXMLValue( phPolynomial, "polynomialCoefficients", "None" );
if ( EQUAL( pszPolyCoeff, "None" ) )
{
CPLFree( phRPC );
phRPC = NULL;
return;
}
papszCeoff = CSLTokenizeString2( pszPolyCoeff, " ", CSLT_STRIPLEADSPACES );
if( CSLCount( papszCeoff ) != 20 )
{
CPLFree( phRPC );
phRPC = NULL;
return;
}
for( i = 0; i < 20; i++ )
{
phRPC->adfSAMP_DEN_COEFF[anOrder[i] - 1] = CPLAtof( papszCeoff[i] );
}
}
// ---------------------------------------------------------------------------
// SetRPC()
// ---------------------------------------------------------------------------
void GeoRasterWrapper::SetRPC()
{
// -------------------------------------------------------------------
// Remove "layerInfo" tree
// -------------------------------------------------------------------
CPLXMLNode* phLayerInfo = CPLGetXMLNode( phMetadata, "layerInfo" );
CPLXMLNode* phClone = NULL;
if( phLayerInfo )
{
phClone = CPLCloneXMLTree( phLayerInfo );
CPLRemoveXMLChild( phMetadata, phLayerInfo );
}
// -------------------------------------------------------------------
// Start loading the RPC to "spatialReferenceInfo" tree
// -------------------------------------------------------------------
int i = 0;
CPLString osField, osMultiField;
CPLXMLNode* phPolynomial = NULL;
CPLXMLNode* phSRSInfo = CPLGetXMLNode( phMetadata,
"spatialReferenceInfo" );
if( ! phSRSInfo )
{
phSRSInfo = CPLCreateXMLNode( phMetadata, CXT_Element,
"spatialReferenceInfo" );
}
else
{
CPLXMLNode* phNode = NULL;
phNode = CPLGetXMLNode( phSRSInfo, "isReferenced" );
if( phNode )
{
CPLRemoveXMLChild( phSRSInfo, phNode );
}
phNode = CPLGetXMLNode( phSRSInfo, "SRID" );
if( phNode )
{
CPLRemoveXMLChild( phSRSInfo, phNode );
}
phNode = CPLGetXMLNode( phSRSInfo, "modelCoordinateLocation" );
if( phNode )
{
CPLRemoveXMLChild( phSRSInfo, phNode );
}
phNode = CPLGetXMLNode( phSRSInfo, "modelType" );
if( phNode )
{
CPLRemoveXMLChild( phSRSInfo, phNode );
}
phNode = CPLGetXMLNode( phSRSInfo, "polynomialModel" );
if( phNode )
{
CPLRemoveXMLChild( phSRSInfo, phNode );
}
}
CPLCreateXMLElementAndValue( phSRSInfo, "isReferenced", "true" );
CPLCreateXMLElementAndValue( phSRSInfo, "SRID", "4327" );
CPLCreateXMLElementAndValue( phSRSInfo, "modelCoordinateLocation",
"CENTER" );
CPLCreateXMLElementAndValue( phSRSInfo, "modelType", "FunctionalFitting" );
CPLSetXMLValue( phSRSInfo, "polynomialModel.#rowOff",
CPLSPrintf( "%.15g", phRPC->dfLINE_OFF ) );
CPLSetXMLValue( phSRSInfo, "polynomialModel.#columnOff",
CPLSPrintf( "%.15g", phRPC->dfSAMP_OFF ) );
CPLSetXMLValue( phSRSInfo, "polynomialModel.#xOff",
CPLSPrintf( "%.15g", phRPC->dfLONG_OFF ) );
CPLSetXMLValue( phSRSInfo, "polynomialModel.#yOff",
CPLSPrintf( "%.15g", phRPC->dfLAT_OFF ) );
CPLSetXMLValue( phSRSInfo, "polynomialModel.#zOff",
CPLSPrintf( "%.15g", phRPC->dfHEIGHT_OFF ) );
CPLSetXMLValue( phSRSInfo, "polynomialModel.#rowScale",
CPLSPrintf( "%.15g", phRPC->dfLINE_SCALE ) );
CPLSetXMLValue( phSRSInfo, "polynomialModel.#columnScale",
CPLSPrintf( "%.15g", phRPC->dfSAMP_SCALE ) );
CPLSetXMLValue( phSRSInfo, "polynomialModel.#xScale",
CPLSPrintf( "%.15g", phRPC->dfLONG_SCALE ) );
CPLSetXMLValue( phSRSInfo, "polynomialModel.#yScale",
CPLSPrintf( "%.15g", phRPC->dfLAT_SCALE ) );
CPLSetXMLValue( phSRSInfo, "polynomialModel.#zScale",
CPLSPrintf( "%.15g", phRPC->dfHEIGHT_SCALE ) );
CPLXMLNode* phPloyModel = CPLGetXMLNode( phSRSInfo, "polynomialModel" );
// pPolynomial refers to LINE_NUM
CPLSetXMLValue( phPloyModel, "pPolynomial.#pType", "1" );
CPLSetXMLValue( phPloyModel, "pPolynomial.#nVars", "3" );
CPLSetXMLValue( phPloyModel, "pPolynomial.#order", "3" );
CPLSetXMLValue( phPloyModel, "pPolynomial.#nCoefficients", "20" );
for( i = 0; i < 20; i++ )
{
osField.Printf( "%.15g", phRPC->adfLINE_NUM_COEFF[anOrder[i] - 1] );
if( i > 0 )
osMultiField += " ";
else
osMultiField = "";
osMultiField += osField;
}
phPolynomial = CPLGetXMLNode( phPloyModel, "pPolynomial" );
CPLCreateXMLElementAndValue( phPolynomial, "polynomialCoefficients",
osMultiField );
// qPolynomial refers to LINE_DEN
CPLSetXMLValue( phPloyModel, "qPolynomial.#pType", "1" );
CPLSetXMLValue( phPloyModel, "qPolynomial.#nVars", "3" );
CPLSetXMLValue( phPloyModel, "qPolynomial.#order", "3" );
CPLSetXMLValue( phPloyModel, "qPolynomial.#nCoefficients", "20" );
for( i = 0; i < 20; i++ )
{
osField.Printf( "%.15g", phRPC->adfLINE_DEN_COEFF[anOrder[i] - 1] );
if( i > 0 )
osMultiField += " ";
else
osMultiField = "";
osMultiField += osField;
}
phPolynomial = CPLGetXMLNode( phPloyModel, "qPolynomial" );
CPLCreateXMLElementAndValue( phPolynomial, "polynomialCoefficients",
osMultiField );
// rPolynomial refers to SAMP_NUM
CPLSetXMLValue( phPloyModel, "rPolynomial.#pType", "1" );
CPLSetXMLValue( phPloyModel, "rPolynomial.#nVars", "3" );
CPLSetXMLValue( phPloyModel, "rPolynomial.#order", "3" );
CPLSetXMLValue( phPloyModel, "rPolynomial.#nCoefficients", "20" );
for( i = 0; i < 20; i++ )
{
osField.Printf( "%.15g", phRPC->adfSAMP_NUM_COEFF[anOrder[i] - 1] );
if( i > 0 )
osMultiField += " ";
else
osMultiField = "";
osMultiField += osField;
}
phPolynomial = CPLGetXMLNode( phPloyModel, "rPolynomial" );
CPLCreateXMLElementAndValue( phPolynomial, "polynomialCoefficients",
osMultiField );
// sPolynomial refers to SAMP_DEN
CPLSetXMLValue( phPloyModel, "sPolynomial.#pType", "1" );
CPLSetXMLValue( phPloyModel, "sPolynomial.#nVars", "3" );
CPLSetXMLValue( phPloyModel, "sPolynomial.#order", "3" );
CPLSetXMLValue( phPloyModel, "sPolynomial.#nCoefficients", "20" );
for( i = 0; i < 20; i++ )
{
osField.Printf( "%.15g", phRPC->adfSAMP_DEN_COEFF[anOrder[i] - 1] );
if( i > 0 )
osMultiField += " ";
else
osMultiField = "";
osMultiField += osField;
}
phPolynomial = CPLGetXMLNode( phPloyModel, "sPolynomial" );
CPLCreateXMLElementAndValue( phPolynomial, "polynomialCoefficients",
osMultiField );
// -------------------------------------------------------------------
// Add "layerInfo" tree back
// -------------------------------------------------------------------
CPLAddXMLChild( phMetadata, phClone );
}
// ---------------------------------------------------------------------------
// GetNoData()
// ---------------------------------------------------------------------------
bool GeoRasterWrapper::GetNoData( int nLayer, double* pdfNoDataValue )
{
if( psNoDataList == NULL || CPLListCount( psNoDataList ) == 0 )
{
return false;
}
// -------------------------------------------------------------------
// Get only single value NoData, no list of values or value ranges
// -------------------------------------------------------------------
int nCount = 0;
double dfValue = 0.0;
CPLList* psList = NULL;
// -------------------------------------------------------------------
// Process Object Layer values
// -------------------------------------------------------------------
for( psList = psNoDataList; psList ; psList = psList->psNext )
{
hNoDataItem* phItem = (hNoDataItem*) psList->pData;
if( phItem->nBand == 0 )
{
if( phItem->dfLower == phItem->dfUpper )
{
dfValue = phItem->dfLower;
nCount++;
}
else
{
return false; // value range
}
}
}
// -------------------------------------------------------------------
// Values from the Object Layer override values from the layers
// -------------------------------------------------------------------
if( nCount == 1 )
{
*pdfNoDataValue = dfValue;
return true;
}
// -------------------------------------------------------------------
// Process SubLayer values
// -------------------------------------------------------------------
for( psList = psNoDataList; psList ; psList = psList->psNext )
{
hNoDataItem* phItem = (hNoDataItem*) psList->pData;
if( phItem->nBand == nLayer )
{
if( phItem->dfLower == phItem->dfUpper )
{
dfValue = phItem->dfLower;
nCount++;
}
else
{
return false; // value range
}
}
}
if( nCount == 1 )
{
*pdfNoDataValue = dfValue;
return true;
}
return false;
}
// ---------------------------------------------------------------------------
// SetNoDataValue()
// ---------------------------------------------------------------------------
bool GeoRasterWrapper::SetNoData( int nLayer, const char* pszValue )
{
// ------------------------------------------------------------
// Set one NoData per dataset on "rasterInfo" section (10g)
// ------------------------------------------------------------
if( poConnection->GetVersion() < 11 )
{
CPLXMLNode* psRInfo = CPLGetXMLNode( phMetadata, "rasterInfo" );
CPLXMLNode* psNData = CPLSearchXMLNode( psRInfo, "NODATA" );
if( psNData == NULL )
{
psNData = CPLCreateXMLNode( NULL, CXT_Element, "NODATA" );
CPLXMLNode* psCDepth = CPLGetXMLNode( psRInfo, "cellDepth" );
CPLXMLNode* psPointer = psCDepth->psNext;
psCDepth->psNext = psNData;
psNData->psNext = psPointer;
}
CPLSetXMLValue( psRInfo, "NODATA", pszValue );
bFlushMetadata = true;
return true;
}
// ------------------------------------------------------------
// Add NoData for all bands (layer=0) or for a specific band
// ------------------------------------------------------------
char szRDT[OWCODE];
char szNoData[OWTEXT];
strcpy( szRDT, sDataTable.c_str() );
strcpy( szNoData, pszValue );
int nRID = nRasterId;
// ------------------------------------------------------------
// Write the in memory XML metada to avoid lossing other changes
// ------------------------------------------------------------
char* pszMetadata = CPLSerializeXMLTree( phMetadata );
if( pszMetadata == NULL )
{
return false;
}
OCILobLocator* phLocatorR = NULL;
OCILobLocator* phLocatorW = NULL;
OWStatement* poStmt = poConnection->CreateStatement( CPLSPrintf(
"DECLARE\n"
" GR1 sdo_georaster;\n"
"BEGIN\n"
" SELECT %s INTO GR1 FROM %s%s T WHERE %s FOR UPDATE;\n"
"\n"
" GR1.metadata := sys.xmltype.createxml(:1);\n"
"\n"
" SDO_GEOR.addNODATA( GR1, :2, :3 );\n"
"\n"
" UPDATE %s%s T SET %s = GR1 WHERE %s;\n"
"\n"
" EXECUTE IMMEDIATE\n"
" 'SELECT T.%s.METADATA.getClobVal() FROM %s%s T \n"
" WHERE T.%s.RASTERDATATABLE = UPPER(:1)\n"
" AND T.%s.RASTERID = :2'\n"
" INTO :metadata USING :rdt, :rid;\n"
"\n"
" COMMIT;\n"
"END;",
sColumn.c_str(), sSchema.c_str(), sTable.c_str(), sWhere.c_str(),
sSchema.c_str(), sTable.c_str(), sColumn.c_str(), sWhere.c_str(),
sColumn.c_str(), sSchema.c_str(), sTable.c_str(),
sColumn.c_str(),
sColumn.c_str() ) );
poStmt->WriteCLob( &phLocatorW, pszMetadata );
poStmt->Bind( &phLocatorW );
poStmt->Bind( &nLayer );
poStmt->Bind( szNoData );
poStmt->BindName( ":metadata", &phLocatorR );
poStmt->BindName( ":rdt", szRDT );
poStmt->BindName( ":rid", &nRID );
CPLFree( pszMetadata );
if( ! poStmt->Execute() )
{
OCIDescriptorFree( phLocatorR, OCI_DTYPE_LOB );
OCIDescriptorFree( phLocatorW, OCI_DTYPE_LOB );
delete poStmt;
return false;
}
OCIDescriptorFree( phLocatorW, OCI_DTYPE_LOB );
// ------------------------------------------------------------
// Read the XML metadata from db to memory with nodata updates
// ------------------------------------------------------------
char* pszXML = poStmt->ReadCLob( phLocatorR );
if( pszXML )
{
CPLDestroyXMLNode( phMetadata );
phMetadata = CPLParseXMLString( pszXML );
CPLFree( pszXML );
}
OCIDescriptorFree( phLocatorR, OCI_DTYPE_LOB );
bFlushMetadata = true;
delete poStmt;
return false;
}
// ---------------------------------------------------------------------------
// SetVAT()
// ---------------------------------------------------------------------------
bool GeoRasterWrapper::SetVAT( int nBand, const char* pszName )
{
InitializeLayersNode();
bFlushMetadata = true;
int n = 1;
CPLXMLNode* psLayers = CPLGetXMLNode( phMetadata, "layerInfo.subLayer" );
for( ; psLayers; psLayers = psLayers->psNext, n++ )
{
if( n != nBand )
{
continue;
}
CPLXMLNode* psVAT = CPLGetXMLNode( psLayers, "vatTableName" );
if( psVAT != NULL )
{
CPLRemoveXMLChild( psLayers, psVAT );
CPLDestroyXMLNode( psVAT );
}
CPLCreateXMLElementAndValue(psLayers, "vatTableName", pszName );
// ------------------------------------------------------------
// To be updated at Flush Metadata in SDO_GEOR.setVAT()
// ------------------------------------------------------------
sValueAttributeTab = pszName;
return true;
}
return false;
}
// ---------------------------------------------------------------------------
// GetVAT()
// ---------------------------------------------------------------------------
char* GeoRasterWrapper::GetVAT( int nBand )
{
CPLXMLNode* psLayers = CPLGetXMLNode( phMetadata, "layerInfo.subLayer" );
if( psLayers == NULL )
{
return NULL;
}
char* pszTablename = NULL;
int n = 1;
for( ; psLayers; psLayers = psLayers->psNext, n++ )
{
if( n != nBand )
{
continue;
}
CPLXMLNode* psVAT = CPLGetXMLNode( psLayers, "vatTableName" );
if( psVAT != NULL )
{
pszTablename = CPLStrdup(
CPLGetXMLValue( psLayers, "vatTableName", "" ) );
}
break;
}
return pszTablename;
}
// ---------------------------------------------------------------------------
// FlushMetadata()
// ---------------------------------------------------------------------------
bool GeoRasterWrapper::FlushMetadata()
{
if( bFlushBlock )
{
FlushBlock( nCacheBlockId );
}
if( ! bFlushMetadata )
{
return true;
}
bFlushMetadata = false;
// --------------------------------------------------------------------
// Change the isBlank setting left by SDO_GEOR.createBlank() to 'false'
// --------------------------------------------------------------------
CPLXMLNode* psOInfo = CPLGetXMLNode( phMetadata, "objectInfo" );
CPLXMLNode* psNode = NULL;
CPLSetXMLValue( psOInfo, "isBlank", "false" );
psNode = CPLGetXMLNode( psOInfo, "blankCellValue" );
if( psNode != NULL )
{
CPLRemoveXMLChild( psOInfo, psNode );
CPLDestroyXMLNode( psNode );
}
const char* pszRed = "1";
const char* pszGreen = "1";
const char* pszBlue = "1";
if( ( nRasterBands > 2 ) &&
( ! HasColorMap( 1 ) ) &&
( ! HasColorMap( 2 ) ) &&
( ! HasColorMap( 3 ) ) )
{
pszRed = "1";
pszGreen = "2";
pszBlue = "3";
}
psNode = CPLGetXMLNode( psOInfo, "defaultRed" );
if( psNode )
{
CPLRemoveXMLChild( psOInfo, psNode );
CPLDestroyXMLNode( psNode );
}
CPLCreateXMLElementAndValue( psOInfo, "defaultRed", pszRed );
psNode = CPLGetXMLNode( psOInfo, "defaultGreen" );
if( psNode )
{
CPLRemoveXMLChild( psOInfo, psNode );
CPLDestroyXMLNode( psNode );
}
CPLCreateXMLElementAndValue( psOInfo, "defaultGreen", pszGreen );
psNode = CPLGetXMLNode( psOInfo, "defaultBlue" );
if( psNode )
{
CPLRemoveXMLChild( psOInfo, psNode );
CPLDestroyXMLNode( psNode );
}
CPLCreateXMLElementAndValue( psOInfo, "defaultBlue", pszBlue );
// --------------------------------------------------------------------
// Set compression
// --------------------------------------------------------------------
psNode = CPLGetXMLNode( phMetadata, "rasterInfo.compression" );
if( psNode )
{
CPLSetXMLValue( psNode, "type", sCompressionType.c_str() );
if( EQUALN( sCompressionType.c_str(), "JPEG", 4 ) )
{
CPLSetXMLValue( psNode, "quality",
CPLSPrintf( "%d", nCompressQuality ) );
}
}
// --------------------------------------------------------------------
// Update BitmapMask info
// --------------------------------------------------------------------
if( bHasBitmapMask )
{
CPLXMLNode* psLayers = CPLGetXMLNode( phMetadata, "layerInfo" );
if( psLayers )
{
CPLCreateXMLElementAndValue( psLayers, "bitmapMask", "true" );
}
}
// --------------------------------------------------------------------
// Update the Metadata directly from the XML text
// --------------------------------------------------------------------
double dfXCoef[3];
double dfYCoef[3];
int nMLC;
dfXCoef[0] = dfXCoefficient[0];
dfXCoef[1] = dfXCoefficient[1];
dfXCoef[2] = dfXCoefficient[2];
dfYCoef[0] = dfYCoefficient[0];
dfYCoef[1] = dfYCoefficient[1];
dfYCoef[2] = dfYCoefficient[2];
if ( eModelCoordLocation == MCL_CENTER )
{
dfXCoef[2] += dfXCoefficient[0] / 2;
dfYCoef[2] += dfYCoefficient[1] / 2;
nMLC = MCL_CENTER;
}
else
{
nMLC = MCL_UPPERLEFT;
}
if( phRPC )
{
SetRPC();
nSRID = 0;
}
// --------------------------------------------------------------------
// Serialize XML metadata to plain text
// --------------------------------------------------------------------
char* pszMetadata = CPLSerializeXMLTree( phMetadata );
if( pszMetadata == NULL )
{
return false;
}
if( bGenSpatialIndex )
{
nExtentSRID = nExtentSRID == 0 ? nSRID : nExtentSRID;
}
else
{
nExtentSRID = 0; /* Set spatialExtent to null */
}
// --------------------------------------------------------------------
// Update GeoRaster Metadata
// --------------------------------------------------------------------
int nException = 0;
OCILobLocator* phLocator = NULL;
OWStatement* poStmt = poConnection->CreateStatement( CPLSPrintf(
"DECLARE\n"
" GR1 sdo_georaster;\n"
" GM1 sdo_geometry;\n"
" SRID number := :1;\n"
" EXT_SRID number := :2;\n"
" VAT varchar2(128);\n"
"BEGIN\n"
"\n"
" SELECT %s INTO GR1 FROM %s%s T WHERE %s FOR UPDATE;\n"
"\n"
" GR1.metadata := sys.xmltype.createxml(:3);\n"
"\n"
" IF SRID != 0 THEN\n"
" SDO_GEOR.georeference( GR1, SRID, :4,"
" SDO_NUMBER_ARRAY(:5, :6, :7), SDO_NUMBER_ARRAY(:8, :9, :10));\n"
" END IF;\n"
"\n"
" IF EXT_SRID = 0 THEN\n"
" GM1 := NULL;\n"
" ELSE\n"
" GM1 := SDO_GEOR.generateSpatialExtent( GR1 );\n"
" IF EXT_SRID != SRID THEN\n"
" GM1 := SDO_CS.transform( GM1, EXT_SRID );\n"
" END IF;\n"
" END IF;\n"
"\n"
" GR1.spatialExtent := GM1;\n"
"\n"
" VAT := '%s';\n"
" IF VAT != '' THEN\n"
" SDO_GEOR.setVAT(GR1, 1, VAT);\n"
" END IF;\n"
"\n"
" BEGIN\n"
" UPDATE %s%s T SET %s = GR1\n"
" WHERE %s;\n"
" EXCEPTION\n"
" WHEN OTHERS THEN\n"
" :except := SQLCODE;\n"
" IF (SQLCODE != -29877) THEN\n"
" RAISE;\n"
" END IF;\n"
" END\n"
"\n"
" COMMIT;\n"
"END;",
sColumn.c_str(),
sSchema.c_str(),
sTable.c_str(),
sWhere.c_str(),
sValueAttributeTab.c_str(),
sSchema.c_str(),
sTable.c_str(),
sColumn.c_str(),
sWhere.c_str() ) );
poStmt->WriteCLob( &phLocator, pszMetadata );
poStmt->Bind( &nSRID );
poStmt->Bind( &nExtentSRID );
poStmt->Bind( &phLocator );
poStmt->Bind( &nMLC );
poStmt->Bind( &dfXCoef[0] );
poStmt->Bind( &dfXCoef[1] );
poStmt->Bind( &dfXCoef[2] );
poStmt->Bind( &dfYCoef[0] );
poStmt->Bind( &dfYCoef[1] );
poStmt->Bind( &dfYCoef[2] );
poStmt->BindName( ":except", &nException );
CPLFree( pszMetadata );
if( ! poStmt->Execute() )
{
OCIDescriptorFree( phLocator, OCI_DTYPE_LOB );
delete poStmt;
return false;
}
OCIDescriptorFree( phLocator, OCI_DTYPE_LOB );
delete poStmt;
if( nException )
{
CPLError( CE_Warning, CPLE_AppDefined,
"Cannot generate spatialExtent! (ORA-%d) ", nException );
}
if (bGenPyramid)
{
if (GeneratePyramid( nPyramidLevels, sPyramidResampling.c_str(), true ))
{
CPLDebug("GEOR", "Generated pyramid successfully.");
}
else
{
CPLError( CE_Warning, CPLE_AppDefined, "Error generating pyramid!");
}
}
return true;
}
// ---------------------------------------------------------------------------
// GeneratePyramid()
// ---------------------------------------------------------------------------
bool GeoRasterWrapper::GeneratePyramid( int nLevels,
const char* pszResampling,
bool bInternal )
{
nPyramidMaxLevel = nLevels;
if( bInternal )
{
CPLString sLevels = "";
if (nLevels > 0)
{
sLevels = CPLSPrintf("rlevel=%d", nLevels);
}
OWStatement* poStmt = poConnection->CreateStatement( CPLSPrintf(
"DECLARE\n"
" gr sdo_georaster;\n"
"BEGIN\n"
" SELECT %s INTO gr FROM %s t WHERE %s FOR UPDATE;\n"
" sdo_geor.generatePyramid(gr, '%s resampling=%s');\n"
" UPDATE %s t SET %s = gr WHERE %s;\n"
" COMMIT;\n"
"END;\n",
sColumn.c_str(),
sTable.c_str(),
sWhere.c_str(),
sLevels.c_str(),
pszResampling,
sTable.c_str(),
sColumn.c_str(),
sWhere.c_str() ) );
if( poStmt->Execute() )
{
delete poStmt;
return true;
}
delete poStmt;
return false;
}
// -----------------------------------------------------------
// Create rows for pyramid levels
// -----------------------------------------------------------
OWStatement* poStmt = NULL;
poStmt = poConnection->CreateStatement(
"DECLARE\n"
" SCL NUMBER := 0;\n"
" RC NUMBER := 0;\n"
" RR NUMBER := 0;\n"
" CBS2 NUMBER := 0;\n"
" RBS2 NUMBER := 0;\n"
" TBB NUMBER := 0;\n"
" TRB NUMBER := 0;\n"
" TCB NUMBER := 0;\n"
" X NUMBER := 0;\n"
" Y NUMBER := 0;\n"
" W NUMBER := 0;\n"
" H NUMBER := 0;\n"
" STM VARCHAR2(1024) := '';\n"
"BEGIN\n"
" EXECUTE IMMEDIATE 'DELETE FROM '||:rdt||' \n"
" WHERE RASTERID = '||:rid||' AND PYRAMIDLEVEL > 0';\n"
" STM := 'INSERT INTO '||:rdt||' VALUES (:1, :2, :3-1, :4-1, :5-1 ,\n"
" SDO_GEOMETRY(2003, NULL, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 3),\n"
" SDO_ORDINATE_ARRAY(:6, :7, :8-1, :9-1)), EMPTY_BLOB() )';\n"
" TBB := :TotalBandBlocks;\n"
" RBS2 := floor(:RowBlockSize / 2);\n"
" CBS2 := floor(:ColumnBlockSize / 2);\n"
" FOR l IN 1..:level LOOP\n"
" SCL := 2 ** l;\n"
" RR := floor(:RasterRows / SCL);\n"
" RC := floor(:RasterColumns / SCL);\n"
" IF (RC <= CBS2) OR (RR <= RBS2) THEN\n"
" H := RR;\n"
" W := RC;\n"
" ELSE\n"
" H := :RowBlockSize;\n"
" W := :ColumnBlockSize;\n"
" END IF;\n"
" TRB := greatest(1, ceil( ceil(:RasterColumns / :ColumnBlockSize) / SCL));\n"
" TCB := greatest(1, ceil( ceil(:RasterRows / :RowBlockSize) / SCL));\n"
" FOR b IN 1..TBB LOOP\n"
" Y := 0;\n"
" FOR r IN 1..TCB LOOP\n"
" X := 0;\n"
" FOR c IN 1..TRB LOOP\n"
" EXECUTE IMMEDIATE STM USING :rid, l, b, r, c, Y, X, (Y+H), (X+W);\n"
" X := X + W;\n"
" END LOOP;\n"
" Y := Y + H;\n"
" END LOOP;\n"
" END LOOP;\n"
" END LOOP;\n"
" COMMIT;\n"
"END;" );
const char* pszDataTable = sDataTable.c_str();
poStmt->BindName( ":rdt", (char*) pszDataTable );
poStmt->BindName( ":rid", &nRasterId );
poStmt->BindName( ":level", &nLevels );
poStmt->BindName( ":TotalBandBlocks", &nTotalBandBlocks );
poStmt->BindName( ":RowBlockSize", &nRowBlockSize );
poStmt->BindName( ":ColumnBlockSize", &nColumnBlockSize );
poStmt->BindName( ":RasterRows", &nRasterRows );
poStmt->BindName( ":RasterColumns", &nRasterColumns );
if( ! poStmt->Execute() )
{
delete poStmt;
return false;
}
CPLXMLNode* psNode = CPLGetXMLNode( phMetadata, "rasterInfo.pyramid" );
if( psNode )
{
CPLSetXMLValue( psNode, "type", "DECREASE" );
CPLSetXMLValue( psNode, "resampling", pszResampling );
CPLSetXMLValue( psNode, "maxLevel", CPLSPrintf( "%d", nLevels ) );
}
bFlushMetadata = true;
return true;
}
// ---------------------------------------------------------------------------
// GeneratePyramid()
// ---------------------------------------------------------------------------
bool GeoRasterWrapper::DeletePyramid()
{
OWStatement* poStmt = poConnection->CreateStatement( CPLSPrintf(
"DECLARE\n"
" gr sdo_georaster;\n"
"BEGIN\n"
" SELECT %s INTO gr FROM %s t WHERE %s FOR UPDATE;\n"
" sdo_geor.deletePyramid(gr);\n"
" UPDATE %s t SET %s = gr WHERE %s;\n"
" COMMIT;\n"
"END;\n",
sColumn.c_str(),
sTable.c_str(),
sWhere.c_str(),
sTable.c_str(),
sColumn.c_str(),
sWhere.c_str() ) );
poStmt->Execute();
delete poStmt;
return false;
}
// ---------------------------------------------------------------------------
// CreateBitmapMask()
// ---------------------------------------------------------------------------
bool GeoRasterWrapper::InitializeMask( int nLevel,
int nBlockColumns,
int nBlockRows,
int nColumnBlocks,
int nRowBlocks,
int nBandBlocks )
{
// -----------------------------------------------------------
// Create rows for the bitmap mask
// -----------------------------------------------------------
OWStatement* poStmt = NULL;
poStmt = poConnection->CreateStatement(
"DECLARE\n"
" W NUMBER := :1;\n"
" H NUMBER := :2;\n"
" BB NUMBER := :3;\n"
" RB NUMBER := :4;\n"
" CB NUMBER := :5;\n"
" X NUMBER := 0;\n"
" Y NUMBER := 0;\n"
" STM VARCHAR2(1024) := '';\n"
"BEGIN\n"
"\n"
" EXECUTE IMMEDIATE 'DELETE FROM '||:rdt||' \n"
" WHERE RASTERID = '||:rid||' AND PYRAMIDLEVEL = '||:lev||' ';\n"
"\n"
" STM := 'INSERT INTO '||:rdt||' VALUES (:1, :lev, :2-1, :3-1, :4-1 ,\n"
" SDO_GEOMETRY(2003, NULL, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 3),\n"
" SDO_ORDINATE_ARRAY(:5, :6, :7-1, :8-1)), EMPTY_BLOB() )';\n"
"\n"
" FOR b IN 1..BB LOOP\n"
" Y := 0;\n"
" FOR r IN 1..RB LOOP\n"
" X := 0;\n"
" FOR c IN 1..CB LOOP\n"
" EXECUTE IMMEDIATE STM USING :rid, b, r, c, Y, X, (Y+H), (X+W);\n"
" X := X + W;\n"
" END LOOP;\n"
" Y := Y + H;\n"
" END LOOP;\n"
" END LOOP;\n"
"END;" );
char pszDataTable[OWNAME];
poStmt->Bind( &nBlockColumns );
poStmt->Bind( &nBlockRows );
poStmt->Bind( &nBandBlocks );
poStmt->Bind( &nRowBlocks );
poStmt->Bind( &nColumnBlocks );
poStmt->BindName( ":rdt", pszDataTable );
poStmt->BindName( ":rid", &nRasterId );
poStmt->BindName( ":lev", &nLevel );
if( ! poStmt->Execute() )
{
delete poStmt;
return false;
}
return true;
}
// ---------------------------------------------------------------------------
// UnpackNBits()
// ---------------------------------------------------------------------------
void GeoRasterWrapper::UnpackNBits( GByte* pabyData )
{
int nPixCount = nColumnBlockSize * nRowBlockSize * nBandBlockSize;
if( EQUAL( sCellDepth.c_str(), "4BIT" ) )
{
for( int ii = nPixCount - 2; ii >= 0; ii -= 2 )
{
int k = ii >> 1;
pabyData[ii+1] = (pabyData[k] ) & 0xf;
pabyData[ii] = (pabyData[k] >> 4) & 0xf;
}
}
else if( EQUAL( sCellDepth.c_str(), "2BIT" ) )
{
for( int ii = nPixCount - 4; ii >= 0; ii -= 4 )
{
int k = ii >> 2;
pabyData[ii+3] = (pabyData[k] ) & 0x3;
pabyData[ii+2] = (pabyData[k] >> 2) & 0x3;
pabyData[ii+1] = (pabyData[k] >> 4) & 0x3;
pabyData[ii] = (pabyData[k] >> 6) & 0x3;
}
}
else
{
for( int ii = nPixCount - 1; ii >= 0; ii-- )
{
if( ( pabyData[ii>>3] & ( 128 >> (ii & 0x7) ) ) )
pabyData[ii] = 1;
else
pabyData[ii] = 0;
}
}
}
// ---------------------------------------------------------------------------
// PackNBits()
// ---------------------------------------------------------------------------
void GeoRasterWrapper::PackNBits( GByte* pabyData )
{
int nPixCount = nBandBlockSize * nRowBlockSize * nColumnBlockSize;
GByte* pabyBuffer = (GByte*) VSIMalloc( nPixCount * sizeof(GByte*) );
if( pabyBuffer == NULL )
{
CPLError( CE_Failure, CPLE_OutOfMemory, "PackNBits" );
return;
}
if( nCellSizeBits == 4 )
{
for( int ii = 0; ii < nPixCount - 1; ii += 2 )
{
int k = ii >> 1;
pabyBuffer[k] =
((((GByte *) pabyData)[ii+1] & 0xf) )
| ((((GByte *) pabyData)[ii] & 0xf) << 4);
}
}
else if( nCellSizeBits == 2 )
{
for( int ii = 0; ii < nPixCount - 3; ii += 4 )
{
int k = ii >> 2;
pabyBuffer[k] =
((((GByte *) pabyData)[ii+3] & 0x3) )
| ((((GByte *) pabyData)[ii+2] & 0x3) << 2)
| ((((GByte *) pabyData)[ii+1] & 0x3) << 4)
| ((((GByte *) pabyData)[ii] & 0x3) << 6);
}
}
else
{
for( int ii = 0; ii < nPixCount - 7; ii += 8 )
{
int k = ii >> 3;
pabyBuffer[k] =
((((GByte *) pabyData)[ii+7] & 0x1) )
| ((((GByte *) pabyData)[ii+6] & 0x1) << 1)
| ((((GByte *) pabyData)[ii+5] & 0x1) << 2)
| ((((GByte *) pabyData)[ii+4] & 0x1) << 3)
| ((((GByte *) pabyData)[ii+3] & 0x1) << 4)
| ((((GByte *) pabyData)[ii+2] & 0x1) << 5)
| ((((GByte *) pabyData)[ii+1] & 0x1) << 6)
| ((((GByte *) pabyData)[ii] & 0x1) << 7);
}
}
memcpy( pabyData, pabyBuffer, nPixCount );
CPLFree( pabyBuffer );
}
// ---------------------------------------------------------------------------
// UncompressJpeg()
// ---------------------------------------------------------------------------
const static int K2Chrominance[64] =
{
17, 18, 24, 47, 99, 99, 99, 99,
18, 21, 26, 66, 99, 99, 99, 99,
24, 26, 56, 99, 99, 99, 99, 99,
47, 66, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99
};
static const int AC_BITS[16] =
{
0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 119
};
static const int AC_HUFFVAL[256] =
{
0, 1, 2, 3, 17, 4, 5, 33, 49, 6, 18,
65, 81, 7, 97, 113, 19, 34, 50, 129, 8, 20,
66, 145, 161, 177, 193, 9, 35, 51, 82, 240, 21,
98, 114, 209, 10, 22, 36, 52, 225, 37, 241, 23,
24, 25, 26, 38, 39, 40, 41, 42, 53, 54, 55,
56, 57, 58, 67, 68, 69, 70, 71, 72, 73, 74,
83, 84, 85, 86, 87, 88, 89, 90, 99, 100, 101,
102, 103, 104, 105, 106, 115, 116, 117, 118, 119, 120,
121, 122, 130, 131, 132, 133, 134, 135, 136, 137, 138,
146, 147, 148, 149, 150, 151, 152, 153, 154, 162, 163,
164, 165, 166, 167, 168, 169, 170, 178, 179, 180, 181,
182, 183, 184, 185, 186, 194, 195, 196, 197, 198, 199,
200, 201, 202, 210, 211, 212, 213, 214, 215, 216, 217,
218, 226, 227, 228, 229, 230, 231, 232, 233, 234, 242,
243, 244, 245, 246, 247, 248, 249, 250
};
static const int DC_BITS[16] =
{
0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0
};
static const int DC_HUFFVAL[256] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
};
/***
*
* Load the tables based on the Java's JAI default values.
*
* JPEGQTable.K2Chrominance.getScaledInstance()
* JPEGHuffmanTable.StdACChrominance
* JPEGHuffmanTable.StdDCChrominance
*
***/
void JPEG_LoadTables( JQUANT_TBL* hquant_tbl_ptr,
JHUFF_TBL* huff_ac_ptr,
JHUFF_TBL* huff_dc_ptr,
unsigned int nQuality )
{
int i = 0;
float fscale_factor;
// --------------------------------------------------------------------
// Scale Quantization table based on quality
// --------------------------------------------------------------------
fscale_factor = (float) jpeg_quality_scaling( nQuality ) / (float) 100.0;
for ( i = 0; i < 64; i++ )
{
UINT16 temp = (UINT16) floor( K2Chrominance[i] * fscale_factor + 0.5 );
if ( temp <= 0 )
temp = 1;
if ( temp > 255 )
temp = 255;
hquant_tbl_ptr->quantval[i] = (UINT16) temp;
}
// --------------------------------------------------------------------
// Load AC huffman table
// --------------------------------------------------------------------
for ( i = 1; i <= 16; i++ )
{
/* counts[i] is number of Huffman codes of length i bits, i=1..16 */
huff_ac_ptr->bits[i] = (UINT8) AC_BITS[i-1];
}
for ( i = 0; i < 256; i++ )
{
/* symbols[] is the list of Huffman symbols, in code-length order */
huff_ac_ptr->huffval[i] = (UINT8) AC_HUFFVAL[i];
}
// --------------------------------------------------------------------
// Load DC huffman table
// --------------------------------------------------------------------
for ( i = 1; i <= 16; i++ )
{
/* counts[i] is number of Huffman codes of length i bits, i=1..16 */
huff_dc_ptr->bits[i] = (UINT8) DC_BITS[i-1];
}
for ( i = 0; i < 256; i++ )
{
/* symbols[] is the list of Huffman symbols, in code-length order */
huff_dc_ptr->huffval[i] = (UINT8) DC_HUFFVAL[i];
}
}
void GeoRasterWrapper::UncompressJpeg( unsigned long nInSize )
{
// --------------------------------------------------------------------
// Load JPEG in a virtual file
// --------------------------------------------------------------------
const char* pszMemFile = CPLSPrintf( "/vsimem/geor_%p.jpg", pabyBlockBuf );
VSILFILE *fpImage = VSIFOpenL( pszMemFile, "wb" );
VSIFWriteL( pabyBlockBuf, nInSize, 1, fpImage );
VSIFCloseL( fpImage );
fpImage = VSIFOpenL( pszMemFile, "rb" );
// --------------------------------------------------------------------
// Initialize decompressor
// --------------------------------------------------------------------
if( ! sDInfo.global_state )
{
sDInfo.err = jpeg_std_error( &sJErr );
jpeg_create_decompress( &sDInfo );
// -----------------------------------------------------------------
// Load table for abbreviated JPEG-B
// -----------------------------------------------------------------
int nComponentsToLoad = -1; /* doesn't load any table */
if( EQUAL( sCompressionType.c_str(), "JPEG-B") )
{
nComponentsToLoad = nBandBlockSize;
}
for( int n = 0; n < nComponentsToLoad; n++ )
{
sDInfo.quant_tbl_ptrs[n] =
jpeg_alloc_quant_table( (j_common_ptr) &sDInfo );
sDInfo.ac_huff_tbl_ptrs[n] =
jpeg_alloc_huff_table( (j_common_ptr) &sDInfo );
sDInfo.dc_huff_tbl_ptrs[n] =
jpeg_alloc_huff_table( (j_common_ptr) &sDInfo );
JPEG_LoadTables( sDInfo.quant_tbl_ptrs[n],
sDInfo.ac_huff_tbl_ptrs[n],
sDInfo.dc_huff_tbl_ptrs[n],
nCompressQuality );
}
}
jpeg_vsiio_src( &sDInfo, fpImage );
jpeg_read_header( &sDInfo, TRUE );
sDInfo.out_color_space = ( nBandBlockSize == 1 ? JCS_GRAYSCALE : JCS_RGB );
jpeg_start_decompress( &sDInfo );
GByte* pabyScanline = pabyBlockBuf;
for( int iLine = 0; iLine < nRowBlockSize; iLine++ )
{
JSAMPLE* ppSamples = (JSAMPLE*) pabyScanline;
jpeg_read_scanlines( &sDInfo, &ppSamples, 1 );
pabyScanline += ( nColumnBlockSize * nBandBlockSize );
}
jpeg_finish_decompress( &sDInfo );
VSIFCloseL( fpImage );
VSIUnlink( pszMemFile );
}
// ---------------------------------------------------------------------------
// CompressJpeg()
// ---------------------------------------------------------------------------
unsigned long GeoRasterWrapper::CompressJpeg( void )
{
// --------------------------------------------------------------------
// Load JPEG in a virtual file
// --------------------------------------------------------------------
const char* pszMemFile = CPLSPrintf( "/vsimem/geor_%p.jpg", pabyBlockBuf );
VSILFILE *fpImage = VSIFOpenL( pszMemFile, "wb" );
bool write_all_tables = TRUE;
if( EQUAL( sCompressionType.c_str(), "JPEG-B") )
{
write_all_tables = FALSE;
}
// --------------------------------------------------------------------
// Initialize compressor
// --------------------------------------------------------------------
if( ! sCInfo.global_state )
{
sCInfo.err = jpeg_std_error( &sJErr );
jpeg_create_compress( &sCInfo );
jpeg_vsiio_dest( &sCInfo, fpImage );
sCInfo.image_width = nColumnBlockSize;
sCInfo.image_height = nRowBlockSize;
sCInfo.input_components = nBandBlockSize;
sCInfo.in_color_space = (nBandBlockSize == 1 ? JCS_GRAYSCALE : JCS_RGB);
jpeg_set_defaults( &sCInfo );
sCInfo.JFIF_major_version = 1;
sCInfo.JFIF_minor_version = 2;
jpeg_set_quality( &sCInfo, nCompressQuality, TRUE );
// -----------------------------------------------------------------
// Load table for abbreviated JPEG-B
// -----------------------------------------------------------------
int nComponentsToLoad = -1; /* doesn't load any table */
if( EQUAL( sCompressionType.c_str(), "JPEG-B") )
{
nComponentsToLoad = nBandBlockSize;
}
for( int n = 0; n < nComponentsToLoad; n++ )
{
sCInfo.quant_tbl_ptrs[n] =
jpeg_alloc_quant_table( (j_common_ptr) &sCInfo );
sCInfo.ac_huff_tbl_ptrs[n] =
jpeg_alloc_huff_table( (j_common_ptr) &sCInfo );
sCInfo.dc_huff_tbl_ptrs[n] =
jpeg_alloc_huff_table( (j_common_ptr) &sCInfo );
JPEG_LoadTables( sCInfo.quant_tbl_ptrs[n],
sCInfo.ac_huff_tbl_ptrs[n],
sCInfo.dc_huff_tbl_ptrs[n],
nCompressQuality );
}
}
else
{
jpeg_vsiio_dest( &sCInfo, fpImage );
}
jpeg_suppress_tables( &sCInfo, ! write_all_tables );
jpeg_start_compress( &sCInfo, write_all_tables );
GByte* pabyScanline = pabyBlockBuf;
for( int iLine = 0; iLine < nRowBlockSize; iLine++ )
{
JSAMPLE* ppSamples = (JSAMPLE*) pabyScanline;
jpeg_write_scanlines( &sCInfo, &ppSamples, 1 );
pabyScanline += ( nColumnBlockSize * nBandBlockSize );
}
jpeg_finish_compress( &sCInfo );
VSIFCloseL( fpImage );
fpImage = VSIFOpenL( pszMemFile, "rb" );
size_t nSize = VSIFReadL( pabyCompressBuf, 1, nBlockBytes, fpImage );
VSIFCloseL( fpImage );
VSIUnlink( pszMemFile );
return (unsigned long) nSize;
}
// ---------------------------------------------------------------------------
// UncompressDeflate()
// ---------------------------------------------------------------------------
bool GeoRasterWrapper::UncompressDeflate( unsigned long nBufferSize )
{
GByte* pabyBuf = (GByte*) VSIMalloc( nBufferSize );
if( pabyBuf == NULL )
{
CPLError( CE_Failure, CPLE_OutOfMemory, "UncompressDeflate" );
return false;
}
memcpy( pabyBuf, pabyBlockBuf, nBufferSize );
// Call ZLib uncompress
unsigned long nDestLen = nBlockBytes;
int nRet = uncompress( pabyBlockBuf, &nDestLen, pabyBuf, nBufferSize );
CPLFree( pabyBuf );
if( nRet != Z_OK )
{
CPLError( CE_Failure, CPLE_AppDefined, "ZLib return code (%d)", nRet );
return false;
}
if( nDestLen != nBlockBytes )
{
CPLError( CE_Failure, CPLE_AppDefined,
"ZLib decompressed buffer size (%ld) expected (%ld)", nDestLen, nBlockBytes );
return false;
}
return true;
}
// ---------------------------------------------------------------------------
// CompressDeflate()
// ---------------------------------------------------------------------------
unsigned long GeoRasterWrapper::CompressDeflate( void )
{
unsigned long nLen = ((unsigned long)(nBlockBytes * 1.1)) + 12;
GByte* pabyBuf = (GByte*) VSIMalloc( nBlockBytes );
if( pabyBuf == NULL )
{
CPLError( CE_Failure, CPLE_OutOfMemory, "CompressDeflate" );
return 0;
}
memcpy( pabyBuf, pabyBlockBuf, nBlockBytes );
// Call ZLib compress
int nRet = compress( pabyCompressBuf, &nLen, pabyBuf, nBlockBytes );
CPLFree( pabyBuf );
if( nRet != Z_OK )
{
CPLError( CE_Failure, CPLE_AppDefined, "ZLib return code (%d)", nRet );
return 0;
}
return nLen;
}