LCOV - code coverage report
Current view: directory - frmts/arg - argdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 385 298 77.4 %
Date: 2013-03-30 Functions: 16 12 75.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: argdataset.cpp 24855 2012-08-25 21:12:55Z rouault $
       3                 :  *
       4                 :  * Project:  Azavea Raster Grid format driver.
       5                 :  * Purpose:  Implements support for reading and writing Azavea Raster Grid
       6                 :  *           format.
       7                 :  * Author:   David Zwarg <dzwarg@azavea.com>
       8                 :  *
       9                 :  ******************************************************************************
      10                 :  * Copyright (c) 2012, David Zwarg <dzwarg@azavea.com>
      11                 :  *
      12                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      13                 :  * copy of this software and associated documentation files (the "Software"),
      14                 :  * to deal in the Software without restriction, including without limitation
      15                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      16                 :  * and/or sell copies of the Software, and to permit persons to whom the
      17                 :  * Software is furnished to do so, subject to the following conditions:
      18                 :  *
      19                 :  * The above copyright notice and this permission notice shall be included
      20                 :  * in all copies or substantial portions of the Software.
      21                 :  *
      22                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      23                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      24                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      25                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      26                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      27                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      28                 :  * DEALINGS IN THE SOFTWARE.
      29                 :  ****************************************************************************/
      30                 : 
      31                 : #include "rawdataset.h"
      32                 : #include "cpl_string.h"
      33                 : #include "jsonc/json.h"
      34                 : #include "jsonc/json_util.h"
      35                 : #include <ogr_spatialref.h>
      36                 : 
      37                 : CPL_CVSID("$Id: argdataset.cpp 24855 2012-08-25 21:12:55Z rouault $");
      38                 : 
      39                 : #define MAX_FILENAME_LEN 4096
      40                 : 
      41                 : #ifndef NAN
      42                 : #  ifdef HUGE_VAL
      43                 : #    define NAN (HUGE_VAL * 0.0)
      44                 : #  else
      45                 : 
      46                 : static float CPLNaN(void)
      47                 : {
      48                 :     float fNan;
      49                 :     int nNan = 0x7FC00000;
      50                 :     memcpy(&fNan, &nNan, 4);
      51                 :     return fNan;
      52                 : }
      53                 : 
      54                 : #    define NAN CPLNaN()
      55                 : #  endif
      56                 : #endif
      57                 : 
      58                 : /************************************************************************/
      59                 : /* ==================================================================== */
      60                 : /*        ARGDataset                                        */
      61                 : /* ==================================================================== */
      62                 : /************************************************************************/
      63                 : 
      64                 : class ARGDataset : public RawDataset
      65                 : {
      66                 :         VSILFILE  *fpImage; // image data file.
      67                 :     
      68                 :         double  adfGeoTransform[6];
      69                 :         char * pszFilename;
      70                 : 
      71                 :     public:
      72                 :         ARGDataset();
      73                 :         ~ARGDataset();
      74                 : 
      75                 :         CPLErr  GetGeoTransform( double * padfTransform );
      76                 :    
      77                 :         static int Identify( GDALOpenInfo * );
      78                 :         static GDALDataset *Open( GDALOpenInfo * );
      79                 :         static GDALDataset *CreateCopy( const char *, GDALDataset *, int, 
      80                 :             char **, GDALProgressFunc, void *);
      81                 :         virtual char ** GetFileList(void);
      82                 : }; 
      83                 : 
      84                 : /************************************************************************/
      85                 : /*                            ARGDataset()                              */
      86                 : /************************************************************************/
      87                 : 
      88              48 : ARGDataset::ARGDataset()
      89                 : {
      90              48 :     adfGeoTransform[0] = 0.0;
      91              48 :     adfGeoTransform[1] = 1.0;
      92              48 :     adfGeoTransform[2] = 0.0;
      93              48 :     adfGeoTransform[3] = 0.0;
      94              48 :     adfGeoTransform[4] = 0.0;
      95              48 :     adfGeoTransform[5] = 1.0;
      96              48 :     fpImage = NULL;
      97              48 : }
      98                 : 
      99                 : /************************************************************************/
     100                 : /*                            ~ARGDataset()                             */
     101                 : /************************************************************************/
     102                 : 
     103              48 : ARGDataset::~ARGDataset()
     104                 : 
     105                 : {
     106              48 :     CPLFree(pszFilename);
     107                 : 
     108              48 :     FlushCache();
     109              48 :     if( fpImage != NULL )
     110              46 :         VSIFCloseL( fpImage );
     111              48 : }
     112                 : 
     113                 : /************************************************************************/
     114                 : /*                          GetGeoTransform()                           */
     115                 : /************************************************************************/
     116                 : 
     117              25 : CPLErr ARGDataset::GetGeoTransform( double * padfTransform )
     118                 : 
     119                 : {
     120              25 :     memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
     121                 : 
     122              25 :     return CE_None;
     123                 : }
     124                 : 
     125                 : /************************************************************************/
     126                 : /*                         GetJsonFilename()                            */
     127                 : /************************************************************************/
     128             141 : CPLString GetJsonFilename(CPLString pszFilename) 
     129                 : {
     130             141 :     return CPLSPrintf( "%s/%s.json", CPLGetDirname(pszFilename), CPLGetBasename(pszFilename) );
     131                 : }
     132                 : 
     133                 : /************************************************************************/
     134                 : /*                           GetJsonObject()                            */
     135                 : /************************************************************************/
     136             122 : json_object * GetJsonObject(CPLString pszFilename) 
     137                 : {
     138             122 :     json_object * pJSONObject = NULL;
     139             122 :     CPLString pszJSONFilename = GetJsonFilename(pszFilename);
     140                 : 
     141             122 :     pJSONObject = json_object_from_file((char *)pszJSONFilename.c_str());
     142             122 :     if (pJSONObject == (struct json_object*)error_ptr(-1) || pJSONObject == NULL) {
     143                 :         CPLDebug("ARGDataset", "GetJsonObject(): "
     144               8 :             "Could not parse JSON file.");
     145               8 :         return NULL;
     146                 :     }
     147                 : 
     148             114 :     return pJSONObject;
     149                 : }
     150                 : 
     151                 : /************************************************************************/
     152                 : /*                          GetJsonValueStr()                           */
     153                 : /************************************************************************/
     154             688 : const char * GetJsonValueStr(json_object * pJSONObject, CPLString pszKey) 
     155                 : {
     156             688 :     json_object * pJSONItem = json_object_object_get(pJSONObject, pszKey.c_str());
     157             688 :     if (pJSONItem == NULL) {
     158                 :         CPLDebug("ARGDataset", "GetJsonValueStr(): "
     159             105 :             "Could not find '%s' in JSON.", pszKey.c_str());
     160             105 :         return NULL;
     161                 :     }
     162                 : 
     163             583 :     return json_object_get_string(pJSONItem);
     164                 : }
     165                 : 
     166                 : /************************************************************************/
     167                 : /*                          GetJsonValueDbl()                           */
     168                 : /************************************************************************/
     169             528 : double GetJsonValueDbl(json_object * pJSONObject, CPLString pszKey) 
     170                 : {
     171             528 :     const char *pszJSONStr = GetJsonValueStr(pJSONObject, pszKey.c_str());
     172                 :     char *pszTmp;
     173                 :     double fTmp;
     174             528 :     if (pszJSONStr == NULL) {
     175             105 :         return NAN;
     176                 :     }
     177             423 :     pszTmp = (char *)pszJSONStr;
     178             423 :     fTmp = CPLStrtod(pszJSONStr, &pszTmp);
     179             423 :     if (pszTmp == pszJSONStr) {
     180                 :         CPLDebug("ARGDataset", "GetJsonValueDbl(): "
     181               0 :             "Key value is not a numeric value: %s:%s", pszKey.c_str(), pszTmp);
     182               0 :         return NAN;
     183                 :     }
     184                 : 
     185             423 :     return fTmp;
     186                 : }
     187                 : 
     188                 : /************************************************************************/
     189                 : /*                           GetJsonValueInt()                          */
     190                 : /************************************************************************/
     191             144 : int GetJsonValueInt(json_object * pJSONObject, CPLString pszKey) 
     192                 : {
     193             144 :     double fTmp = GetJsonValueDbl(pJSONObject, pszKey.c_str());
     194             144 :     if (CPLIsNan(fTmp)) {
     195              35 :         return -1;
     196                 :     }
     197                 : 
     198             109 :     return (int)fTmp;
     199                 : }
     200                 : 
     201                 : /************************************************************************/
     202                 : /*                            GetFileList()                             */
     203                 : /************************************************************************/
     204               0 : char ** ARGDataset::GetFileList()
     205                 : {
     206               0 :     char **papszFileList = GDALPamDataset::GetFileList();
     207               0 :     CPLString pszJSONFilename = GetJsonFilename(pszFilename);
     208                 : 
     209               0 :     papszFileList = CSLAddString( papszFileList, pszJSONFilename );
     210                 : 
     211               0 :     return papszFileList;
     212                 : }
     213                 : 
     214                 : /************************************************************************/
     215                 : /*                              Identify()                              */
     216                 : /************************************************************************/
     217                 : 
     218           11963 : int ARGDataset::Identify( GDALOpenInfo *poOpenInfo )
     219                 : {
     220                 :     json_object * pJSONObject;
     221           11963 :     if (!EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "arg")) {
     222           11897 :         return FALSE;
     223                 :     }
     224                 : 
     225              66 :     pJSONObject = GetJsonObject(poOpenInfo->pszFilename);
     226              66 :     if (pJSONObject == NULL) {
     227               8 :         return FALSE;
     228                 :     }
     229                 : 
     230              58 :     json_object_put(pJSONObject);
     231              58 :     pJSONObject = NULL;
     232                 : 
     233              58 :     return TRUE;
     234                 : }
     235                 : 
     236                 : /************************************************************************/
     237                 : /*                                Open()                                */
     238                 : /************************************************************************/
     239            1832 : GDALDataset *ARGDataset::Open( GDALOpenInfo * poOpenInfo )
     240                 : {
     241                 :     json_object * pJSONObject;
     242                 :     const char * pszJSONStr;
     243                 :     char * pszLayer;
     244                 :     /***** items from the json metadata *****/
     245            1832 :     GDALDataType eType = GDT_Unknown;
     246            1832 :     double fXmin = 0.0;
     247            1832 :     double fYmin = 0.0;
     248            1832 :     double fXmax = 0.0;
     249            1832 :     double fYmax = 0.0;
     250            1832 :     double fCellwidth = 1.0;
     251            1832 :     double fCellheight = 1.0;
     252            1832 :     double fXSkew = 0.0;
     253            1832 :     double fYSkew = 0.0;
     254            1832 :     int nRows = 0;
     255            1832 :     int nCols = 0;
     256            1832 :     int nSrs = 3857;
     257                 :     /***** items from the json metadata *****/
     258            1832 :     int nPixelOffset = 0;
     259            1832 :     double fNoDataValue = NAN;
     260                 : 
     261            1832 :     char * pszWKT = NULL;
     262            1832 :     OGRSpatialReference oSRS;
     263            1832 :     OGRErr nErr = OGRERR_NONE;
     264                 : 
     265            1832 :     if ( !Identify( poOpenInfo ) )
     266            1776 :         return NULL;
     267                 : 
     268                 : /* -------------------------------------------------------------------- */
     269                 : /*      Check metadata settings in JSON.                                */
     270                 : /* -------------------------------------------------------------------- */
     271                 : 
     272              56 :     pJSONObject = GetJsonObject(poOpenInfo->pszFilename);
     273                 : 
     274              56 :     if (pJSONObject == NULL) {
     275               0 :         CPLError(CE_Failure, CPLE_AppDefined, "Error parsing JSON.");
     276               0 :         return NULL;
     277                 :     }
     278                 : 
     279                 :     // get the type (always 'arg')
     280              56 :     pszJSONStr = GetJsonValueStr(pJSONObject, "type");
     281              56 :     if (pszJSONStr == NULL ) {
     282                 :         CPLError(CE_Failure, CPLE_AppDefined,
     283               0 :             "The ARG 'type' is missing from the JSON file.");
     284               0 :         json_object_put(pJSONObject);
     285               0 :         pJSONObject = NULL;
     286               0 :         return NULL;
     287                 :     }
     288              56 :     else if (!EQUAL(pszJSONStr, "arg")) {
     289                 :         CPLError(CE_Failure, CPLE_AppDefined,
     290               0 :             "The ARG 'type' is not recognized: '%s'.", pszJSONStr);
     291               0 :         json_object_put(pJSONObject);
     292               0 :         pJSONObject = NULL;
     293               0 :         return NULL;
     294                 :     }
     295                 : 
     296                 :     // get the datatype
     297              56 :     pszJSONStr = GetJsonValueStr(pJSONObject, "datatype");
     298              56 :     if (pszJSONStr == NULL) {
     299                 :         CPLError(CE_Failure, CPLE_AppDefined,
     300               0 :             "The ARG 'datatype' is missing from the JSON file.");
     301               0 :         json_object_put(pJSONObject);
     302               0 :         pJSONObject = NULL;
     303               0 :         return NULL;
     304                 :     }
     305              56 :     else if (EQUAL(pszJSONStr, "int8")) {
     306                 :         CPLDebug("ARGDataset", "Open(): "
     307               5 :             "int8 data is not supported in GDAL -- mapped to uint8");
     308               5 :         eType = GDT_Byte; 
     309               5 :         nPixelOffset = 1;
     310               5 :         fNoDataValue = 128;
     311                 :     }
     312              51 :     else if (EQUAL(pszJSONStr, "int16")) {
     313              10 :         eType = GDT_Int16;
     314              10 :         nPixelOffset = 2;
     315              10 :         fNoDataValue = -32767;
     316                 :     }
     317              41 :     else if (EQUAL(pszJSONStr, "int32")) {
     318               5 :         eType = GDT_Int32;
     319               5 :         nPixelOffset = 4;
     320               5 :         fNoDataValue = -2e31;
     321                 :     }
     322              36 :     else if (EQUAL(pszJSONStr, "uint8")) {
     323               8 :         eType = GDT_Byte; 
     324               8 :         nPixelOffset = 1;
     325               8 :         fNoDataValue = 255;
     326                 :     }
     327              28 :     else if (EQUAL(pszJSONStr, "uint16")) {
     328               5 :         eType = GDT_UInt16;
     329               5 :         nPixelOffset = 2;
     330               5 :         fNoDataValue = 65535;
     331                 :     }
     332              23 :     else if (EQUAL(pszJSONStr, "uint32")) {
     333               5 :         eType = GDT_UInt32;
     334               5 :         nPixelOffset = 4;
     335               5 :         fNoDataValue = -2e31;
     336                 :     }
     337              18 :     else if (EQUAL(pszJSONStr, "float32")) {
     338               5 :         eType = GDT_Float32;
     339               5 :         nPixelOffset = 4;
     340               5 :         fNoDataValue = NAN;
     341                 :     }
     342              13 :     else if (EQUAL(pszJSONStr, "float64")) { 
     343               5 :         eType = GDT_Float64;
     344               5 :         nPixelOffset = 8;
     345               5 :         fNoDataValue = NAN;
     346                 :     }
     347                 :     else {
     348              16 :         if (EQUAL(pszJSONStr, "int64") ||
     349                 :             EQUAL(pszJSONStr, "uint64")) {
     350                 :             CPLError(CE_Failure, CPLE_AppDefined,
     351               8 :                 "The ARG 'datatype' is unsupported in GDAL: '%s'.", pszJSONStr);
     352                 :         }
     353                 :         else {
     354                 :             CPLError(CE_Failure, CPLE_AppDefined,
     355               0 :                 "The ARG 'datatype' is unknown: '%s'.", pszJSONStr);
     356                 :         }
     357               8 :         json_object_put(pJSONObject);
     358               8 :         pJSONObject = NULL;
     359               8 :         return NULL;
     360                 :     }
     361                 : 
     362                 :     // get the xmin of the bounding box
     363              48 :     fXmin = GetJsonValueDbl(pJSONObject, "xmin");
     364              48 :     if (CPLIsNan(fXmin)) {
     365                 :         CPLError(CE_Failure, CPLE_AppDefined,
     366               0 :             "The ARG 'xmin' is missing or invalid.");
     367               0 :         json_object_put(pJSONObject);
     368               0 :         pJSONObject = NULL;
     369               0 :         return NULL;
     370                 :     }
     371                 :     
     372                 :     // get the ymin of the bounding box
     373              48 :     fYmin = GetJsonValueDbl(pJSONObject, "ymin");
     374              48 :     if (CPLIsNan(fYmin)) {
     375                 :         CPLError(CE_Failure, CPLE_AppDefined,
     376               0 :             "The ARG 'ymin' is missing or invalid.");
     377               0 :         json_object_put(pJSONObject);
     378               0 :         pJSONObject = NULL;
     379               0 :         return NULL;
     380                 :     }
     381                 : 
     382                 :     // get the xmax of the bounding box
     383              48 :     fXmax = GetJsonValueDbl(pJSONObject, "xmax");
     384              48 :     if (CPLIsNan(fXmax)) {
     385                 :         CPLError(CE_Failure, CPLE_AppDefined,
     386               0 :             "The ARG 'xmax' is missing or invalid.");
     387               0 :         json_object_put(pJSONObject);
     388               0 :         pJSONObject = NULL;
     389               0 :         return NULL;
     390                 :     }
     391                 : 
     392                 :     // get the ymax of the bounding box
     393              48 :     fYmax = GetJsonValueDbl(pJSONObject, "ymax");
     394              48 :     if (CPLIsNan(fYmax)) {
     395                 :         CPLError(CE_Failure, CPLE_AppDefined,
     396               0 :             "The ARG 'ymax' is missing or invalid.");
     397               0 :         json_object_put(pJSONObject);
     398               0 :         pJSONObject = NULL;
     399               0 :         return NULL;
     400                 :     }
     401                 : 
     402                 :     // get the cell width
     403              48 :     fCellwidth = GetJsonValueDbl(pJSONObject, "cellwidth");
     404              48 :     if (CPLIsNan(fCellwidth)) {
     405                 :         CPLError(CE_Failure, CPLE_AppDefined,
     406               0 :             "The ARG 'cellwidth' is missing or invalid.");
     407               0 :         json_object_put(pJSONObject);
     408               0 :         pJSONObject = NULL;
     409               0 :         return NULL;
     410                 :     }
     411                 : 
     412                 :     // get the cell height
     413              48 :     fCellheight = GetJsonValueDbl(pJSONObject, "cellheight");
     414              48 :     if (CPLIsNan(fCellheight)) {
     415                 :         CPLError(CE_Failure, CPLE_AppDefined,
     416               0 :             "The ARG 'cellheight' is missing or invalid.");
     417               0 :         json_object_put(pJSONObject);
     418               0 :         pJSONObject = NULL;
     419               0 :         return NULL;
     420                 :     }
     421                 : 
     422              48 :     fXSkew = GetJsonValueDbl(pJSONObject, "xskew");
     423              48 :     if (CPLIsNan(fXSkew)) {
     424                 :         // not an error -- default to 0.0
     425              35 :         fXSkew = 0.0f;
     426                 :     }
     427                 : 
     428              48 :     fYSkew = GetJsonValueDbl(pJSONObject, "yskew");
     429              48 :     if (CPLIsNan(fYSkew)) {
     430                 :         // not an error -- default to 0.0
     431              35 :         fYSkew = 0.0f;
     432                 :     }
     433                 : 
     434                 :     // get the rows
     435              48 :     nRows = GetJsonValueInt(pJSONObject, "rows");
     436              48 :     if (nRows < 0) {
     437                 :         CPLError(CE_Failure, CPLE_AppDefined,
     438               0 :             "The ARG 'rows' is missing or invalid.");
     439               0 :         json_object_put(pJSONObject);
     440               0 :         pJSONObject = NULL;
     441               0 :         return NULL;
     442                 :     }
     443                 : 
     444                 :     // get the columns
     445              48 :     nCols = GetJsonValueInt(pJSONObject, "cols");
     446              48 :     if (nCols < 0) {
     447                 :         CPLError(CE_Failure, CPLE_AppDefined,
     448               0 :             "The ARG 'cols' is missing or invalid.");
     449               0 :         json_object_put(pJSONObject);
     450               0 :         pJSONObject = NULL;
     451               0 :         return NULL;
     452                 :     }
     453                 : 
     454              48 :     nSrs = GetJsonValueInt(pJSONObject, "epsg");
     455              48 :     if (nSrs < 0) {
     456                 :         // not an error -- default to web mercator
     457              35 :         nSrs = 3857;
     458                 :     }
     459                 : 
     460              48 :     nErr = oSRS.importFromEPSG(nSrs);
     461              48 :     if (nErr != OGRERR_NONE) {
     462               0 :         nErr = oSRS.importFromEPSG(3857);
     463                 : 
     464               0 :         if (nErr == OGRERR_NONE) {
     465                 :             CPLDebug("ARGDataset", "Open(): "
     466               0 :                 "The EPSG provided did not import cleanly. Defaulting to EPSG:3857");
     467                 :         }
     468                 :         else {
     469                 :             CPLError(CE_Failure, CPLE_AppDefined,
     470                 :                 "The 'epsg' value did not transate to a known spatial reference."
     471               0 :                 " Please check the 'epsg' value and try again.");
     472                 : 
     473               0 :             json_object_put(pJSONObject);
     474               0 :             pJSONObject = NULL;
     475                 : 
     476               0 :             return NULL;
     477                 :         }
     478                 :     }
     479                 : 
     480              48 :     nErr = oSRS.exportToWkt(&pszWKT);
     481              48 :     if (nErr != OGRERR_NONE) {
     482                 :         CPLError(CE_Failure, CPLE_AppDefined,
     483                 :             "The spatial reference is known, but could not be set on the "
     484               0 :             "dataset. Please check the 'epsg' value and try again.");
     485                 : 
     486               0 :         json_object_put(pJSONObject);
     487               0 :         pJSONObject = NULL;
     488                 : 
     489               0 :         return NULL;
     490                 :     }
     491                 : 
     492                 :     // get the layer (always the file basename)
     493              48 :     pszJSONStr = GetJsonValueStr(pJSONObject, "layer");
     494              48 :     if (pszJSONStr == NULL) {
     495                 :         CPLError(CE_Failure, CPLE_AppDefined,
     496               0 :             "The ARG 'layer' is missing from the JSON file.");
     497               0 :         json_object_put(pJSONObject);
     498               0 :         pJSONObject = NULL;
     499               0 :         return NULL;
     500                 :     }
     501                 : 
     502              48 :     pszLayer = CPLStrdup(pszJSONStr);
     503                 : 
     504                 :     // done with the json object now
     505              48 :     json_object_put(pJSONObject);
     506              48 :     pJSONObject = NULL;
     507                 : 
     508                 : /* -------------------------------------------------------------------- */
     509                 : /*      Create a corresponding GDALDataset.                             */
     510                 : /* -------------------------------------------------------------------- */
     511                 :     ARGDataset *poDS;
     512                 : 
     513              48 :     poDS = new ARGDataset();
     514                 : 
     515              96 :     poDS->pszFilename = CPLStrdup(poOpenInfo->pszFilename);
     516              48 :     poDS->SetMetadataItem("LAYER",pszLayer,NULL);
     517              48 :     poDS->nRasterXSize = nCols;
     518              48 :     poDS->nRasterYSize = nRows;
     519              48 :     poDS->SetProjection( pszWKT );
     520                 : 
     521                 :     // done with the projection string
     522              48 :     CPLFree(pszWKT);
     523              48 :     CPLFree(pszLayer);
     524                 : 
     525                 : /* -------------------------------------------------------------------- */
     526                 : /*      Assume ownership of the file handled from the GDALOpenInfo.     */
     527                 : /* -------------------------------------------------------------------- */
     528              48 :     poDS->fpImage = VSIFOpenL(poOpenInfo->pszFilename, "rb");
     529              48 :     if (poDS->fpImage == NULL)
     530                 :     {
     531               2 :         delete poDS;
     532                 :         CPLError(CE_Failure, CPLE_AppDefined,
     533               2 :             "Could not open dataset '%s'", poOpenInfo->pszFilename);
     534               2 :         return NULL;
     535                 :     }
     536                 : 
     537              46 :     poDS->adfGeoTransform[0] = fXmin;
     538              46 :     poDS->adfGeoTransform[1] = fCellwidth;
     539              46 :     poDS->adfGeoTransform[2] = fXSkew;
     540              46 :     poDS->adfGeoTransform[3] = fYmax;
     541              46 :     poDS->adfGeoTransform[4] = fYSkew;
     542              46 :     poDS->adfGeoTransform[5] = -fCellheight;
     543                 :     
     544                 : /* -------------------------------------------------------------------- */
     545                 : /*      Create band information objects.                                */
     546                 : /* -------------------------------------------------------------------- */
     547                 :     RawRasterBand *poBand;
     548                 : 
     549                 : #ifdef CPL_LSB
     550              46 :     int bNative = FALSE;
     551                 : #else
     552                 :     int bNative = TRUE;
     553                 : #endif
     554                 : 
     555                 :     poBand = new RawRasterBand( poDS, 1, poDS->fpImage,
     556                 :                                 0, nPixelOffset, nPixelOffset * nCols,
     557              46 :                                 eType, bNative, TRUE );
     558              46 :     poDS->SetBand( 1, poBand );
     559                 : 
     560              46 :     poBand->SetNoDataValue( fNoDataValue );
     561                 : 
     562                 : /* -------------------------------------------------------------------- */
     563                 : /*      Initialize any PAM information.                                 */
     564                 : /* -------------------------------------------------------------------- */
     565              46 :     poDS->SetDescription( poOpenInfo->pszFilename );
     566              46 :     poDS->TryLoadXML();
     567                 :     
     568                 : /* -------------------------------------------------------------------- */
     569                 : /*      Check for overviews.                                            */
     570                 : /* -------------------------------------------------------------------- */
     571              46 :     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
     572                 : 
     573              46 :     return( poDS );
     574                 : }
     575                 : 
     576                 : /************************************************************************/
     577                 : /*                          CreateCopy()                                */
     578                 : /************************************************************************/
     579              28 : GDALDataset * ARGDataset::CreateCopy( const char * pszFilename, 
     580                 :     GDALDataset * poSrcDS, int bStrict, char ** papszOptions, 
     581                 :     GDALProgressFunc pfnProgress, void * pProgressData ) 
     582                 : {
     583              28 :     int nBands = poSrcDS->GetRasterCount();
     584              28 :     int nXSize = poSrcDS->GetRasterXSize();
     585              28 :     int nYSize = poSrcDS->GetRasterYSize();
     586                 :     int nXBlockSize, nYBlockSize, nPixelOffset;
     587                 :     GDALDataType eType;
     588              28 :     CPLString pszJSONFilename;
     589              28 :     CPLString pszDataType;
     590              28 :     json_object * poJSONObject = NULL;
     591                 :     double adfTransform[6];
     592              28 :     GDALRasterBand * poSrcBand = NULL;
     593              28 :     RawRasterBand * poDstBand = NULL;
     594              28 :     VSILFILE * fpImage = NULL;
     595                 :     void * pabyData;
     596              28 :     OGRSpatialReference oSRS;
     597              28 :     char * pszWKT = NULL;
     598              28 :     char ** pszTokens = NULL;
     599              28 :     const char * pszLayer = NULL;
     600              28 :     int nSrs = 0;
     601              28 :     OGRErr nErr = OGRERR_NONE;
     602                 :     CPLErr eErr;
     603                 : 
     604              28 :     if( nBands != 1 )
     605                 :     {
     606                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     607               5 :               "ARG driver doesn't support %d bands.  Must be 1 band.", nBands );
     608               5 :         return NULL;
     609                 :     }
     610                 : 
     611              23 :     eType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
     612              23 :     if( eType == GDT_Unknown || 
     613                 :         eType == GDT_CInt16 || 
     614                 :         eType == GDT_CInt32 ||
     615                 :         eType == GDT_CFloat32 || 
     616                 :         eType == GDT_CFloat64 )
     617                 :     {
     618                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     619                 :                   "ARG driver doesn't support data type %s.",
     620               4 :                   GDALGetDataTypeName(eType) );
     621               4 :         return NULL;
     622                 :     }
     623              19 :     else if (eType == GDT_Int16) {
     624               3 :         pszDataType = "int16";
     625               3 :         nPixelOffset = 2;
     626                 :     }
     627              16 :     else if (eType == GDT_Int32) {
     628               2 :         pszDataType = "int32";
     629               2 :         nPixelOffset = 4;
     630                 :     }
     631              14 :     else if (eType == GDT_Byte) {
     632               6 :         pszDataType = "uint8";
     633               6 :         nPixelOffset = 1;
     634                 :     }
     635               8 :     else if (eType == GDT_UInt16) {
     636               2 :         pszDataType = "uint16";
     637               2 :         nPixelOffset = 2;
     638                 :     }
     639               6 :     else if (eType == GDT_UInt32) {
     640               2 :         pszDataType = "uint32";
     641               2 :         nPixelOffset = 4;
     642                 :     }
     643               4 :     else if (eType == GDT_Float32) {
     644               2 :         pszDataType = "float32";
     645               2 :         nPixelOffset = 4;
     646                 :     }
     647               2 :     else if (eType == GDT_Float64) {
     648               2 :         pszDataType = "float64";
     649               2 :         nPixelOffset = 8;
     650                 :     }
     651                 : 
     652              19 :     poSrcDS->GetGeoTransform( adfTransform );
     653                 : 
     654              19 :     pszWKT = (char *)poSrcDS->GetProjectionRef();
     655              19 :     nErr = oSRS.importFromWkt(&pszWKT);
     656              19 :     if (nErr != OGRERR_NONE) {
     657                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     658               0 :               "Cannot import spatial reference WKT from source dataset.");
     659               0 :         return NULL;
     660                 :     }
     661                 : 
     662              19 :     if (oSRS.GetAuthorityCode("PROJCS") != NULL) {
     663              10 :         nSrs = atoi(oSRS.GetAuthorityCode("PROJCS"));
     664                 :     }
     665               9 :     else if (oSRS.GetAuthorityCode("GEOGCS") != NULL) {
     666               7 :         nSrs = atoi(oSRS.GetAuthorityCode("GEOGCS"));
     667                 :     }
     668                 :     else {
     669                 :         // could not determine projected or geographic code
     670                 :         // default to EPSG:3857 if no code could be found
     671               2 :         nSrs = 3857;
     672                 :     }
     673                 : 
     674                 :     /********************************************************************/
     675                 :     /* Create JSON companion file.                                      */
     676                 :     /********************************************************************/
     677              19 :     pszJSONFilename = GetJsonFilename(pszFilename);
     678              19 :     if (pszJSONFilename == NULL) {
     679                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     680               0 :                   "ARG driver can't determine filename for companion file.");
     681               0 :         return NULL;
     682                 :     }
     683                 : 
     684              19 :     poJSONObject = json_object_new_object();
     685                 : 
     686              19 :     pszTokens = poSrcDS->GetMetadata();
     687              19 :     pszLayer = CSLFetchNameValue(pszTokens, "LAYER");
     688                 : 
     689              19 :     if ( pszLayer == NULL) {
     690                 :         // Set the layer
     691                 :         json_object_object_add(poJSONObject, "layer", json_object_new_string(
     692                 :             CPLGetBasename(pszJSONFilename)
     693              10 :         ));
     694                 :     }
     695                 :     else {
     696                 :         // Set the layer
     697                 :         json_object_object_add(poJSONObject, "layer", json_object_new_string(
     698                 :             pszLayer
     699               9 :         ));
     700                 :     }
     701                 : 
     702                 :     // Set the type
     703              19 :     json_object_object_add(poJSONObject, "type", json_object_new_string("arg"));
     704                 :     // Set the datatype
     705              19 :     json_object_object_add(poJSONObject, "datatype", json_object_new_string(pszDataType));
     706                 :     // Set the number of rows
     707              19 :     json_object_object_add(poJSONObject, "rows", json_object_new_int(nYSize));
     708                 :     // Set the number of columns
     709              19 :     json_object_object_add(poJSONObject, "cols", json_object_new_int(nXSize));
     710                 :     // Set the xmin
     711              19 :     json_object_object_add(poJSONObject, "xmin", json_object_new_double(adfTransform[0]));
     712                 :     // Set the ymax
     713              19 :     json_object_object_add(poJSONObject, "ymax", json_object_new_double(adfTransform[3]));
     714                 :     // Set the cellwidth
     715              19 :     json_object_object_add(poJSONObject, "cellwidth", json_object_new_double(adfTransform[1]));
     716                 :     // Set the cellheight
     717              19 :     json_object_object_add(poJSONObject, "cellheight", json_object_new_double(-adfTransform[5]));
     718                 :     // Set the xmax
     719              19 :     json_object_object_add(poJSONObject, "xmax", json_object_new_double(adfTransform[0] + nXSize * adfTransform[1]));
     720                 :     // Set the ymin
     721              19 :     json_object_object_add(poJSONObject, "ymin", json_object_new_double(adfTransform[3] + nYSize * adfTransform[5]));
     722                 :     // Set the xskew
     723              19 :     json_object_object_add(poJSONObject, "xskew", json_object_new_double(adfTransform[2]));
     724                 :     // Set the yskew
     725              19 :     json_object_object_add(poJSONObject, "yskew", json_object_new_double(adfTransform[4]));
     726              19 :     if (nSrs > 0) {
     727                 :         // Set the epsg
     728              19 :         json_object_object_add(poJSONObject, "epsg", json_object_new_int(nSrs));
     729                 :     }
     730                 : 
     731              19 :     if (json_object_to_file((char *)pszJSONFilename.c_str(), poJSONObject) < 0) {
     732                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     733               2 :                   "ARG driver can't write companion file.");
     734                 : 
     735               2 :         json_object_put(poJSONObject);
     736               2 :         poJSONObject = NULL;
     737                 : 
     738               2 :         return NULL;
     739                 :     }
     740                 : 
     741              17 :     json_object_put(poJSONObject);
     742              17 :     poJSONObject = NULL;
     743                 : 
     744              17 :     fpImage = VSIFOpenL(pszFilename, "wb");
     745              17 :     if (fpImage == NULL)
     746                 :     {
     747                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     748               0 :               "ARG driver can't create data file %s.", pszFilename);
     749                 : 
     750                 :         // remove JSON file
     751               0 :         VSIUnlink( pszJSONFilename.c_str() );
     752                 : 
     753               0 :         return NULL;
     754                 :     }
     755                 : 
     756                 :     // only 1 raster band
     757              17 :     poSrcBand = poSrcDS->GetRasterBand( 1 );
     758                 : 
     759                 : #ifdef CPL_LSB
     760              17 :     int bNative = FALSE;
     761                 : #else
     762                 :     int bNative = TRUE;
     763                 : #endif
     764                 : 
     765                 :     poDstBand = new RawRasterBand( fpImage, 0, nPixelOffset, 
     766              17 :         nPixelOffset * nXSize, eType, bNative, nXSize, nYSize, TRUE, FALSE);
     767                 : 
     768              17 :     poSrcBand->GetBlockSize(&nXBlockSize, &nYBlockSize);
     769                 : 
     770              17 :     pabyData = CPLMalloc(nXBlockSize * nPixelOffset);
     771                 : 
     772                 :     // convert any blocks into scanlines
     773              55 :     for (int nYBlock = 0; nYBlock * nYBlockSize < nYSize; nYBlock++) {
     774             651 :         for (int nYScanline = 0; nYScanline < nYBlockSize; nYScanline++) {
     775             613 :             if ((nYScanline+1) + nYBlock * nYBlockSize > poSrcBand->GetYSize() ) {
     776              13 :                 continue;
     777                 :             }
     778                 : 
     779            1200 :             for (int nXBlock = 0; nXBlock * nXBlockSize < nXSize; nXBlock++) {
     780                 :                 int nXValid;
     781                 : 
     782             600 :                 if( (nXBlock+1) * nXBlockSize > poSrcBand->GetXSize() )
     783               0 :                     nXValid = poSrcBand->GetXSize() - nXBlock * nXBlockSize;
     784                 :                 else
     785             600 :                     nXValid = nXBlockSize;
     786                 : 
     787                 :                 eErr = poSrcBand->RasterIO(GF_Read, nXBlock * nXBlockSize, 
     788                 :                     nYBlock * nYBlockSize + nYScanline, nXValid, 1, pabyData, nXBlockSize, 
     789             600 :                     1, eType, 0, 0);
     790                 : 
     791             600 :                 if (eErr != CE_None) {
     792               0 :                     CPLError(CE_Failure, CPLE_AppDefined, "Error reading.");
     793                 : 
     794               0 :                     CPLFree( pabyData );
     795               0 :                     delete poDstBand;
     796               0 :                     VSIFCloseL( fpImage );
     797                 : 
     798               0 :                     return NULL;
     799                 :                 }
     800                 : 
     801                 :                 eErr = poDstBand->RasterIO(GF_Write, nXBlock * nXBlockSize, 
     802                 :                     nYBlock * nYBlockSize + nYScanline, nXValid, 1, pabyData, nXBlockSize, 
     803             600 :                     1, eType, 0, 0);
     804                 : 
     805             600 :                 if (eErr != CE_None) {
     806               0 :                     CPLError(CE_Failure, CPLE_AppDefined, "Error writing.");
     807                 : 
     808               0 :                     CPLFree( pabyData );
     809               0 :                     delete poDstBand;
     810               0 :                     VSIFCloseL( fpImage );
     811                 : 
     812               0 :                     return NULL;
     813                 :                 }
     814                 :             }
     815                 :         }
     816                 :     }
     817                 : 
     818              17 :     CPLFree( pabyData );
     819              17 :     delete poDstBand;
     820              17 :     VSIFCloseL( fpImage );
     821                 : 
     822              17 :     return (GDALDataset *)GDALOpen( pszFilename, GA_ReadOnly );
     823                 : }
     824                 : 
     825                 : /************************************************************************/
     826                 : /*                          GDALRegister_ARG()                          */
     827                 : /************************************************************************/
     828                 : 
     829             610 : void GDALRegister_ARG()
     830                 : {
     831                 :     GDALDriver  *poDriver;
     832                 : 
     833             610 :     if( GDALGetDriverByName( "ARG" ) == NULL )
     834                 :     {
     835             588 :         poDriver = new GDALDriver();
     836                 :         
     837             588 :         poDriver->SetDescription( "ARG" );
     838                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
     839             588 :                                    "Azavea Raster Grid format" );
     840                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
     841             588 :                                    "frmt_various.html#ARG" );
     842             588 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
     843                 : 
     844             588 :         poDriver->pfnIdentify = ARGDataset::Identify;
     845             588 :         poDriver->pfnOpen = ARGDataset::Open;
     846             588 :         poDriver->pfnCreateCopy = ARGDataset::CreateCopy;
     847                 : 
     848             588 :         GetGDALDriverManager()->RegisterDriver( poDriver );
     849                 :     }
     850             610 : }
     851                 : 

Generated by: LCOV version 1.7