EVOLUTION-MANAGER
Edit File: postgisrastertilerasterband.cpp
/*********************************************************************** * File : postgisrastertilerasterband.cpp * Project: PostGIS Raster driver * Purpose: GDAL Tile RasterBand implementation for PostGIS Raster * driver * Author: Jorge Arevalo, jorge.arevalo@deimos-space.com * jorgearevalo@libregis.org * Last changes: $Id: $ * *********************************************************************** * Copyright (c) 2009 - 2013, Jorge Arevalo * Copyright (c) 2013, Even Rouault * * 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 "postgisraster.h" /************************ * \brief Constructor ************************/ PostGISRasterTileRasterBand::PostGISRasterTileRasterBand( PostGISRasterTileDataset * poRTDS, int nBand, GDALDataType eDataType, GBool bIsOffline) { /* Basic properties */ this->poDS = poRTDS; this->bIsOffline = bIsOffline; this->nBand = nBand; #if 0 CPLDebug("PostGIS_Raster", "PostGISRasterTileRasterBand::Constructor: Raster tile dataset " "of dimensions %dx%d", poRTDS->GetRasterXSize(), poRTDS->GetRasterYSize()); #endif this->eDataType = eDataType; nRasterXSize = poRTDS->GetRasterXSize(); nRasterYSize = poRTDS->GetRasterYSize(); nBlockXSize = nRasterXSize; nBlockYSize = nRasterYSize; } /************************ * \brief Destructor ************************/ PostGISRasterTileRasterBand::~PostGISRasterTileRasterBand() { } /*********************************************************************** * \brief Returns true if the (only) block is stored in the cache **********************************************************************/ GBool PostGISRasterTileRasterBand::IsCached() { GDALRasterBlock * poBlock = TryGetLockedBlockRef(0, 0); if (poBlock != NULL) { poBlock->DropLock(); return true; } return false; } /***************************************************** * \brief Read a natural block of raster band data *****************************************************/ CPLErr PostGISRasterTileRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff, CPL_UNUSED int nBlockYOff, void * pImage) { CPLString osCommand; PGresult * poResult = NULL; int nWKBLength = 0; int nPixelSize = GDALGetDataTypeSize(eDataType)/8; PostGISRasterTileDataset * poRTDS = (PostGISRasterTileDataset *)poDS; // Get by PKID if (poRTDS->poRDS->pszPrimaryKeyName) { osCommand.Printf("select st_band(%s, %d) from %s.%s where " "%s = '%s'", poRTDS->poRDS->pszColumn, nBand, poRTDS->poRDS->pszSchema, poRTDS->poRDS->pszTable, poRTDS->poRDS->pszPrimaryKeyName, poRTDS->pszPKID); } // Get by upperleft else { CPLLocaleC oCLocale; // Force C locale to avoid commas instead of decimal points (for QGIS e.g.) osCommand.Printf("select st_band(%s, %d) from %s.%s where " "abs(ST_UpperLeftX(%s) - %.8f) < 1e-8 and abs(ST_UpperLeftY(%s) - %.8f) < 1e-8", poRTDS->poRDS->pszColumn, nBand, poRTDS->poRDS->pszSchema, poRTDS->poRDS->pszTable, poRTDS->poRDS->pszColumn, poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_X], poRTDS->poRDS->pszColumn, poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_Y]); } poResult = PQexec(poRTDS->poRDS->poConn, osCommand.c_str()); #ifdef DEBUG_QUERY CPLDebug("PostGIS_Raster", "PostGISRasterTileRasterBand::IReadBlock(): " "Query = \"%s\" --> number of rows = %d", osCommand.c_str(), poResult ? PQntuples(poResult) : 0 ); #endif if (poResult == NULL || PQresultStatus(poResult) != PGRES_TUPLES_OK || PQntuples(poResult) <= 0) { if (poResult) PQclear(poResult); ReportError(CE_Failure, CPLE_AppDefined, "Error getting block of data (upperpixel = %f, %f)", poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_X], poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_Y]); return CE_Failure; } // TODO: Check this if (bIsOffline) { CPLError(CE_Failure, CPLE_AppDefined, "This raster has outdb " "storage. This feature isn't still available"); PQclear(poResult); return CE_Failure; } /* Copy only data size, without payload */ int nExpectedDataSize = nBlockXSize * nBlockYSize * nPixelSize; GByte * pbyData = CPLHexToBinary(PQgetvalue(poResult, 0, 0), &nWKBLength); int nExpectedWKBLength = RASTER_HEADER_SIZE + BAND_SIZE(nPixelSize, nExpectedDataSize); CPLErr eRet = CE_None; if( nWKBLength != nExpectedWKBLength ) { CPLDebug("PostGIS_Raster", "nWKBLength=%d, nExpectedWKBLength=%d", nWKBLength, nExpectedWKBLength ); eRet = CE_Failure; } else { GByte * pbyDataToRead = (GByte*)GET_BAND_DATA(pbyData,1, nPixelSize, nExpectedDataSize); // Do byte-swapping if necessary */ int bIsLittleEndian = (pbyData[0] == 1); #ifdef CPL_LSB int bSwap = !bIsLittleEndian; #else int bSwap = bIsLittleEndian; #endif if( bSwap && nPixelSize > 1 ) { GDALSwapWords( pbyDataToRead, nPixelSize, nBlockXSize * nBlockYSize, nPixelSize ); } memcpy(pImage, pbyDataToRead, nExpectedDataSize); } CPLFree(pbyData); PQclear(poResult); return eRet; }