CPLErr SDERasterBand::GetStatistics( int bApproxOK, int bForce, double *pdfMin, double *pdfMax, double *pdfMean, double *pdfStdDev ) { // if SDE hasn't already cached our statistics, we'll depend on the // GDALRasterBands's method for getting them. bool bHasStats; bHasStats = SE_rasbandinfo_has_stats (*poBand); if (!bHasStats) return GDALRasterBand::GetStatistics( bApproxOK, bForce, pdfMin, pdfMax, pdfMean, pdfStdDev); // bForce has no effect currently. We always go to SDE to get our // stats if SDE has them. // bApproxOK has no effect currently. If we're getting stats from // SDE, we're hoping SDE calculates them in the way we want. long nSDEErr; nSDEErr = SE_rasbandinfo_get_stats_min(*poBand, pdfMin); if( nSDEErr != SE_SUCCESS ) { IssueSDEError( nSDEErr, "SE_rasbandinfo_get_stats_min" ); return CE_Fatal; } nSDEErr = SE_rasbandinfo_get_stats_max(*poBand, pdfMax); if( nSDEErr != SE_SUCCESS ) { IssueSDEError( nSDEErr, "SE_rasbandinfo_get_stats_max" ); return CE_Fatal; } nSDEErr = SE_rasbandinfo_get_stats_mean(*poBand, pdfMean); if( nSDEErr != SE_SUCCESS ) { IssueSDEError( nSDEErr, "SE_rasbandinfo_get_stats_mean" ); return CE_Fatal; } nSDEErr = SE_rasbandinfo_get_stats_stddev(*poBand, pdfStdDev); if( nSDEErr != SE_SUCCESS ) { IssueSDEError( nSDEErr, "SE_rasbandinfo_get_stats_stddev" ); return CE_Fatal; } return CE_None; }
const char *SDEDataset::GetProjectionRef() { long nSDEErr; SE_COORDREF coordref; nSDEErr = SE_coordref_create(&coordref); if( nSDEErr != SE_SUCCESS ) { IssueSDEError( nSDEErr, "SE_coordref_create" ); return FALSE; } if (!hRasterColumn){ CPLError ( CE_Failure, CPLE_AppDefined, "Raster Column not defined"); return (""); } nSDEErr = SE_rascolinfo_get_coordref(hRasterColumn, coordref); if (nSDEErr == SE_NO_COORDREF) { return (""); } if( nSDEErr != SE_SUCCESS ) { IssueSDEError( nSDEErr, "SE_rascolinfo_get_coordref" ); } char szWKT[SE_MAX_SPATIALREF_SRTEXT_LEN]; nSDEErr = SE_coordref_get_description(coordref, szWKT); if (nSDEErr != SE_SUCCESS ) { IssueSDEError( nSDEErr, "SE_coordref_get_description"); } SE_coordref_free(coordref); OGRSpatialReference *poSRS; CPLDebug ("SDERASTER", "SDE says the coordinate system is: %s'", szWKT); poSRS = new OGRSpatialReference(szWKT); poSRS->morphFromESRI(); poSRS->exportToWkt(&pszWKT); poSRS->Release(); return pszWKT; }
GDALDataType SDERasterBand::GetRasterDataType(void) { // Always ask SDE what it thinks our type is. LONG nSDEErr; nSDEErr = SE_rasbandinfo_get_pixel_type(*poBand, &nSDERasterType); if( nSDEErr != SE_SUCCESS ) { IssueSDEError( nSDEErr, "SE_rasbandinfo_get_pixel_type" ); return GDT_Byte; } return MorphESRIRasterType(nSDERasterType); }
int SDERasterBand::GetOverviewCount( void ) { // grab our existing overview count if we have already gotten it, // otherwise request it from SDE and set our member data with it. long nSDEErr; BOOL bSkipLevel; // return nothing if we were an overview band if (nOverview != -1) return 0; nSDEErr = SE_rasbandinfo_get_max_level(*poBand, (long*)&nOverviews, &bSkipLevel); if( nSDEErr != SE_SUCCESS ) { IssueSDEError( nSDEErr, "SE_rasbandinfo_get_band_size" ); } return nOverviews; }
CPLErr SDERasterBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage ) { // grab our Dataset to limit the casting we have to do. SDEDataset *poGDS = (SDEDataset *) poDS; // SDE manages the acquisition of raster data in "TileInfo" objects. // The hTile is the only heap-allocated object in this method, and // we should make sure to delete it at the end. Once we get the // pixel data, we'll memcopy it back on to the pImage pointer. SE_RASTILEINFO hTile; long nSDEErr; nSDEErr = SE_rastileinfo_create(&hTile); if( nSDEErr != SE_SUCCESS ) { IssueSDEError( nSDEErr, "SE_rastileinfo_create" ); return CE_Fatal; } hConstraint = InitializeConstraint( (long*) &nBlockXOff, (long*) &nBlockYOff ); if (!hConstraint) CPLError( CE_Failure, CPLE_AppDefined, "ConstraintInfo initialization failed"); CPLErr error = QueryRaster(hConstraint); if (error != CE_None) return error; long level; nSDEErr = SE_rastileinfo_get_level(hTile, &level); if( nSDEErr != SE_SUCCESS ) { IssueSDEError( nSDEErr, "SE_rastileinfo_get_level" ); return CE_Fatal; } nSDEErr = SE_stream_get_raster_tile(poGDS->hStream, hTile); if( nSDEErr != SE_SUCCESS ) { IssueSDEError( nSDEErr, "SE_stream_get_raster_tile" ); return CE_Fatal; } long row, column; nSDEErr = SE_rastileinfo_get_rowcol(hTile, &row, &column); if( nSDEErr != SE_SUCCESS ) { IssueSDEError( nSDEErr, "SE_rastileinfo_get_level" ); return CE_Fatal; } long length; unsigned char* pixels; nSDEErr = SE_rastileinfo_get_pixel_data(hTile, (void**) &pixels, &length); if( nSDEErr != SE_SUCCESS ) { IssueSDEError( nSDEErr, "SE_rastileinfo_get_pixel_data" ); return CE_Fatal; } int bits_per_pixel = static_cast<int>(dfDepth * 8 + 0.0001); int block_size = (nBlockXSize * bits_per_pixel + 7) / 8 * nBlockYSize; int bitmap_size = (nBlockXSize * nBlockYSize + 7) / 8; if (length == 0) { // ArcSDE says the block has no data in it. // Write 0's and be done with it memset( pImage, 0, nBlockXSize*nBlockYSize*GDALGetDataTypeSize(eDataType)/8); return CE_None; } if ((length == block_size) || (length == (block_size + bitmap_size))) { if (bits_per_pixel >= 8) { memcpy(pImage, pixels, block_size); } else { GByte *p = reinterpret_cast<GByte*>(pImage); int bit_mask = (2 << bits_per_pixel) - 1; int i = 0; for (int y = 0; y < nBlockYSize; ++y) { for (int x = 0; x < nBlockXSize; ++x) { *p++ = (pixels[i >> 3] >> (i & 7)) & bit_mask; i += bits_per_pixel; } i = (i + 7) / 8 * 8; } } } else {
CPLErr SDEDataset::ComputeRasterInfo() { long nSDEErr; SE_RASTERINFO raster; nSDEErr = SE_rasterinfo_create(&raster); if( nSDEErr != SE_SUCCESS ) { IssueSDEError( nSDEErr, "SE_rasterinfo_create" ); return CE_Fatal; } LONG nRasterColumnId = 0; nSDEErr = SE_rascolinfo_get_id( hRasterColumn, &nRasterColumnId); if( nSDEErr != SE_SUCCESS ) { IssueSDEError( nSDEErr, "SE_rascolinfo_get_id" ); return CE_Fatal; } nSDEErr = SE_raster_get_info_by_id( hConnection, nRasterColumnId, 1, raster); if( nSDEErr != SE_SUCCESS ) { IssueSDEError( nSDEErr, "SE_rascolinfo_get_id" ); return CE_Fatal; } LONG nBandsRet; nSDEErr = SE_raster_get_bands( hConnection, raster, &paohSDERasterBands, &nBandsRet); if( nSDEErr != SE_SUCCESS ) { IssueSDEError( nSDEErr, "SE_raster_get_bands" ); return CE_Fatal; } nBands = nBandsRet; SE_RASBANDINFO band; // grab our other stuff from the first band and hope for the best band = paohSDERasterBands[0]; LONG nXSRet, nYSRet; nSDEErr = SE_rasbandinfo_get_band_size( band, &nXSRet, &nYSRet ); if( nSDEErr != SE_SUCCESS ) { IssueSDEError( nSDEErr, "SE_rasbandinfo_get_band_size" ); return CE_Fatal; } nRasterXSize = nXSRet; nRasterYSize = nYSRet; SE_ENVELOPE extent; nSDEErr = SE_rasbandinfo_get_extent(band, &extent); if( nSDEErr != SE_SUCCESS ) { IssueSDEError( nSDEErr, "SE_rasbandinfo_get_extent" ); return CE_Fatal; } dfMinX = extent.minx; dfMinY = extent.miny; dfMaxX = extent.maxx; dfMaxY = extent.maxy; CPLDebug("SDERASTER", "minx: %.5f, miny: %.5f, maxx: %.5f, maxy: %.5f", dfMinX, dfMinY, dfMaxX, dfMaxY); // x0 roughly corresponds to dfMinX // y0 roughly corresponds to dfMaxY // They can be different than the extent parameters because // SDE uses offsets. The following info is from Duarte Carreira // in relation to bug #2063 http://trac.osgeo.org/gdal/ticket/2063 : // Depending on how the data was loaded, the pixel width // or pixel height may include a pixel offset from the nearest // tile boundary. An offset will be indicated by aplus sign // "+" followed by a value. The value indicates the number // of pixels the nearest tile boundary is to the left of // the image for the x dimension or the number of // pixels the nearest tile boundary is above the image for // the y dimension. The offset information is only useful // for advanced application developers who need to know // where the image begins in relation to the underlying tile structure LFLOAT x0, y0; nSDEErr = SE_rasbandinfo_get_tile_origin(band, &x0, &y0); if( nSDEErr != SE_SUCCESS ) { IssueSDEError( nSDEErr, "SE_rasbandinfo_get_tile_origin" ); return CE_Fatal; } CPLDebug("SDERASTER", "Tile origin: %.5f, %.5f", x0, y0); // we also need to adjust dfMaxX and dfMinY otherwise the cell size will change dfMaxX = (x0-dfMinX) + dfMaxX; dfMinY = (y0-dfMaxY) + dfMinY; // adjust the bbox based on the tile origin. dfMinX = MIN(x0, dfMinX); dfMaxY = MAX(y0, dfMaxY); nSDEErr = SE_rasterattr_create(&hAttributes, false); if( nSDEErr != SE_SUCCESS ) { IssueSDEError( nSDEErr, "SE_rasterattr_create" ); return CE_Fatal; } // Grab the pointer for our member variable nSDEErr = SE_stream_create(hConnection, &hStream); if( nSDEErr != SE_SUCCESS ) { IssueSDEError( nSDEErr, "SE_stream_create" ); return CE_Fatal; } for (int i=0; i < nBands; i++) { SetBand( i+1, new SDERasterBand( this, i+1, -1, &(paohSDERasterBands[i]) )); } GDALRasterBand* b = GetRasterBand(1); eDataType = b->GetRasterDataType(); SE_rasterinfo_free(raster); return CE_None; }
GDALDataset *SDEDataset::Open( GDALOpenInfo * poOpenInfo ) { /* -------------------------------------------------------------------- */ /* If we aren't prefixed with SDE: then ignore this datasource. */ /* -------------------------------------------------------------------- */ if( !STARTS_WITH_CI(poOpenInfo->pszFilename, "SDE:") ) return NULL; /* -------------------------------------------------------------------- */ /* Parse arguments on comma. We expect (layer is optional): */ /* SDE:server,instance,database,username,password,layer */ /* -------------------------------------------------------------------- */ char **papszTokens = CSLTokenizeStringComplex( poOpenInfo->pszFilename+4, ",", TRUE, TRUE ); CPLDebug( "SDERASTER", "Open(\"%s\") revealed %d tokens.", poOpenInfo->pszFilename, CSLCount( papszTokens ) ); if( CSLCount( papszTokens ) < 5 || CSLCount( papszTokens ) > 7 ) { CPLError( CE_Failure, CPLE_OpenFailed, "SDE connect string had wrong number of arguments.\n" "Expected 'SDE:server,instance,database,username,password,layer'\n" "The layer name value is optional.\n" "Got '%s'", poOpenInfo->pszFilename ); return NULL; } /* -------------------------------------------------------------------- */ /* Create a corresponding GDALDataset. */ /* -------------------------------------------------------------------- */ SDEDataset *poDS; poDS = new SDEDataset(); /* -------------------------------------------------------------------- */ /* Try to establish connection. */ /* -------------------------------------------------------------------- */ int nSDEErr; SE_ERROR hSDEErrorInfo; nSDEErr = SE_connection_create( papszTokens[0], papszTokens[1], papszTokens[2], papszTokens[3], papszTokens[4], &(hSDEErrorInfo), &(poDS->hConnection) ); if( nSDEErr != SE_SUCCESS ) { IssueSDEError( nSDEErr, "SE_connection_create" ); return NULL; } /* -------------------------------------------------------------------- */ /* Set unprotected concurrency policy, suitable for single */ /* threaded access. */ /* -------------------------------------------------------------------- */ nSDEErr = SE_connection_set_concurrency( poDS->hConnection, SE_UNPROTECTED_POLICY); if( nSDEErr != SE_SUCCESS) { IssueSDEError( nSDEErr, NULL ); return NULL; } /* -------------------------------------------------------------------- */ /* If we were given a layer name, use that directly, otherwise */ /* query for subdatasets. */ /* -------------------------------------------------------------------- */ // Get the RASTER column name if it was set if (CSLCount (papszTokens) == 7) { poDS->pszColumnName = CPLStrdup( papszTokens[6] ); } else { poDS->pszColumnName = CPLStrdup( "RASTER" ); } CPLDebug ("SDERASTER", "SDE Column name is '%s'", poDS->pszColumnName); if (CSLCount( papszTokens ) >= 6 ) { poDS->pszLayerName = CPLStrdup( papszTokens[5] ); nSDEErr = SE_rascolinfo_create (&(poDS->hRasterColumn)); if( nSDEErr != SE_SUCCESS ) { IssueSDEError( nSDEErr, "SE_rastercolumn_create" ); return NULL; } CPLDebug( "SDERASTER", "'%s' raster layer specified... "\ "using it directly with '%s' as the raster column name.", poDS->pszLayerName, poDS->pszColumnName); nSDEErr = SE_rastercolumn_get_info_by_name( poDS->hConnection, poDS->pszLayerName, poDS->pszColumnName, poDS->hRasterColumn); if( nSDEErr != SE_SUCCESS ) { IssueSDEError( nSDEErr, "SE_rastercolumn_get_info_by_name" ); return NULL; } poDS->ComputeRasterInfo(); } else { nSDEErr = SE_rastercolumn_get_info_list(poDS->hConnection, &(poDS->paohSDERasterColumns), &(poDS->nSubDataCount)); if( nSDEErr != SE_SUCCESS ) { IssueSDEError( nSDEErr, "SE_rascolinfo_get_info_list" ); return NULL; } CPLDebug( "SDERASTER", "No layername specified, %d subdatasets available.", poDS->nSubDataCount); for (int i = 0; i < poDS->nSubDataCount; i++) { char szTableName[SE_QUALIFIED_TABLE_NAME+1]; char szColumnName[SE_MAX_COLUMN_LEN+1]; nSDEErr = SE_rascolinfo_get_raster_column (poDS->paohSDERasterColumns[i], szTableName, szColumnName); CPLDebug( "SDERASTER", "Layer '%s' with column '%s' found.", szTableName, szColumnName); if( nSDEErr != SE_SUCCESS ) { IssueSDEError( nSDEErr, "SE_rascolinfo_get_raster_column" ); return NULL; } } return NULL; } CSLDestroy( papszTokens); return( poDS ); }